{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## GEKKO Python Example Applications\n",
    "\n",
    "![GEKKO Optimization Suite](http://apmonitor.com/wiki/uploads/Main/gekko_optimization.png)\n",
    "\n",
    "GEKKO is optimization software for mixed-integer and differential algebraic equations. It is coupled with large-scale solvers for linear, quadratic, nonlinear, and mixed integer programming (LP, QP, NLP, MILP, MINLP). Modes of operation include data reconciliation, real-time optimization, dynamic simulation, and nonlinear predictive control. See the [GEKKO documentation](http://gekko.readthedocs.io/en/latest/overview.html) for additional information.\n",
    "\n",
    "1. Solver Selection\n",
    "2. Solve Linear Equations\n",
    "3. Solve Nonlinear Equations\n",
    "4. Interpolation with Cubic Spline\n",
    "5. Linear and Polynomial Regression\n",
    "6. Nonlinear Regression\n",
    "7. Machine Learning / Artificial Neural Network\n",
    "8. Solve Differential Equation(s)\n",
    "9. Nonlinear Programming Optimization\n",
    "10. Mixed Integer Nonlinear Programming\n",
    "11. Optimal Control with Integral Objective\n",
    "12. Optimal Control with Economic Objective\n",
    "13. Optimal Control: Minimize Final Time\n",
    "14. PID Control Tuning\n",
    "15. Process Simulator\n",
    "16. Moving Horizon Estimation\n",
    "17. Model Predictive Control\n",
    "18. Debugging Resources"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Name: gekko\n",
      "Version: 0.0.4rc3\n",
      "Summary: Optimization software for differential algebraic equations\n",
      "Home-page: https://github.com/BYU-PRISM/GEKKO\n",
      "Author: BYU PRISM Lab\n",
      "Author-email: john_hedengren@byu.edu\n",
      "License: MIT\n",
      "Location: c:\\programdata\\anaconda3\\lib\\site-packages\n",
      "Requires: numpy, flask\n",
      "Required-by: \n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    # import gekko if installed\n",
    "    from gekko import GEKKO\n",
    "except:\n",
    "    # install gekko if error on try\n",
    "    !pip install gekko\n",
    "    from gekko import GEKKO\n",
    "\n",
    "# package information\n",
    "!pip show gekko\n",
    "\n",
    "# upgrade GEKKO to latest version\n",
    "# !pip install --upgrade gekko"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1: Solver selection\n",
    "\n",
    "Solve $y^2=1$ with APOPT solver. See [APMonitor documentation](https://apmonitor.com/wiki/index.php/Main/OptionApmSolver) or [GEKKO documentation](http://gekko.readthedocs.io/en/latest/global.html?highlight=solver#solver) for additional solver options."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "y: [1.0]\n"
     ]
    }
   ],
   "source": [
    "m = GEKKO()           # create GEKKO model\n",
    "y = m.Var(value=2)    # define new variable, initial value=2\n",
    "m.Equation(y**2==1)   # define new equation\n",
    "m.options.SOLVER=1    # change solver (1=APOPT,3=IPOPT)\n",
    "m.solve(disp=False)   # solve locally (remote=False)\n",
    "print('y: ' + str(y.value)) # print variable value"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2: Solve Linear Equations\n",
    "\n",
    "$3\\,x + 2\\,y=1$\n",
    "\n",
    "$x+2\\,y=0$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.5] [-0.25]\n"
     ]
    }
   ],
   "source": [
    "m = GEKKO()            # create GEKKO model\n",
    "x = m.Var()            # define new variable, default=0\n",
    "y = m.Var()            # define new variable, default=0\n",
    "m.Equations([3*x+2*y==1, x+2*y==0])  # equations\n",
    "m.solve(disp=False)    # solve\n",
    "print(x.value,y.value) # print solution"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3: Solve Nonlinear Equations\n",
    "\n",
    "$x+2\\,y=0$\n",
    "\n",
    "$x^2+y^2=1$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-0.8944272, 0.4472136]\n"
     ]
    }
   ],
   "source": [
    "m = GEKKO()             # create GEKKO model\n",
    "x = m.Var(value=0)      # define new variable, initial value=0\n",
    "y = m.Var(value=1)      # define new variable, initial value=1\n",
    "m.Equations([x + 2*y==0, x**2+y**2==1]) # equations\n",
    "m.solve(disp=False)     # solve\n",
    "print([x.value[0],y.value[0]]) # print solution"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4: Interpolation with Cubic Spline\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x15f5b8743c8>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAD8CAYAAACMwORRAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xucl3P+//HHq2kqJYcOS1tpQqLQtKZ0sCrrEGX7sqHM\nOuRQLSHskm/rxy7W+rIkCqElIom1LTktHeSwmrB0pHSaRFOomNJM8/r98Z7a0Vbzafp85vocnvfb\nbW7zua7PNdf1bIzXvOd9va/329wdERFJLzWiDiAiIvGn4i4ikoZU3EVE0pCKu4hIGlJxFxFJQyru\nIiJpSMVdRCQNqbiLiKQhFXcRkTRUM6oLN2rUyHNycqK6vIhISpo9e/Yad29c2XGRFfecnBwKCgqi\nuryISEoys2WxHKduGRGRNKTiLiKShlTcRUTSUGR97jtSUlJCYWEhmzZtijpKxqlTpw7NmjUjOzs7\n6igiEgdJVdwLCwupX78+OTk5mFnUcTKGu7N27VoKCwtp2bJl1HFEJA6Sqltm06ZNNGzYUIW9mpkZ\nDRs21F9MImkkqYo7oMIeEX3fRdJLUnXLiEgKWrUKpk6FL7+Ezp3hmGOgVq2oU2W8pGu5p5Jp06bR\nu3fvHb532mmn8e233ybkujk5OaxZswaALl26JOQaIjvkDgsXwsMPw7p1Yd+jj0J+Plx7LXTpAvvv\nDyeeCN98E23WDKeWe4JMmTKlWq7zzjvvVMt1RPjyS+jbF95+O2w3bw49e8IFF0CvXtCkSXhvxgz4\n5BPYb79w3JVXQrNmcPXVoNFY1UYt9+2MGzeOo48+mnbt2nHeeecBcOGFFzJp0qRtx+y9997bXq9f\nv55evXrRunVrBg8eTFlZGfDj1vWOzlnR9OnTyc3NJTc3l/bt27NhwwamTZvG8ccfv8NzV7Q1y7Rp\n0+jevTt9+/bl8MMPJz8/H3cHYPbs2XTr1o1jjjmGU045hVWrVsXpuyUZY/Zs6NABPvwQRoyABQvg\nlFPCe82bQ/v2cOCB8Ktfwb33wptvwtb7OJs2wfXXh6+fNSu6f0OmcfddfgBjgdXAnJ28b8BIYBHw\nMfCzys7p7hxzzDG+vXnz5v14R7du//1x551Vf78Sc+bM8VatWnlRUZG7u69du9bd3S+44AJ/9tln\ntx1Xr149d3efOnWq165d2xcvXuylpaV+4oknbjuuRYsWXlRUtNNzVtS7d2+fOXOmu7tv2LDBS0pK\nYjr39ln22WcfX7FihW/ZssU7derkb731lm/evNk7d+7sq1evdnf3CRMm+IABA3b47/+v77+Iu3tZ\nmXvnzu4HHeT+4YdVO8fzz7s3aeJeo4b70KHuGzbEN2MGAQo8hhobS8v9MaDnLt4/FWhV/jEQeKCK\nv2ci9+abb3LWWWfRqFEjABo0aFDp13Ts2JGDDz6YrKws+vfvz8yZM3f7nF27duWaa65h5MiRfPvt\nt9SsWTOmc+8oS7NmzahRowa5ubksXbqUhQsXMmfOHE466SRyc3O59dZbKSwsjOn7IZlp/HjIyYEs\nK6P1QRsZ/5TBM8+EVndubtVOesYZMH8+DBoE990XXktCVdrn7u4zzCxnF4f0AcaV/0Z5z8z2M7Mm\n7r7nf/tPm5bY92NUs2bNbV0iZWVlbN68edt72w8hrMqQwmHDhtGrVy+mTJlC165defXVV6t07tq1\na297nZWVRWlpKe5O27Zteffdd3c7l2Se8eNh4ECoUbyB5ziPshU1OP/SSfBwc/Lz9/Dk++4Lo0eH\nLpoWLcK+adPg+OOhhnqI4y0e39GmwIoK24Xl+1LOCSecwLPPPsvatWsB+Prrr4HQfz579mwAJk+e\nTElJybavef/991myZAllZWU888wzHHfccTGds6LFixdz1FFHcf3119OhQwcWLFgQ07lj0bp1a4qK\nirYV95KSEubOnbvb55HMMHw4bCnexFR6cDr/YBrd+X6jMXx4HC+ytbC/9x706AEXXwylpXG8gEA1\n31A1s4FmVmBmBUVFRdV56Zi0bduW4cOH061bN9q1a8c111wDwKWXXsr06dNp164d7777LvXq1dv2\nNR06dGDIkCEcccQRtGzZkjPOOCOmc1Y0YsQIjjzySI4++miys7M59dRTYzp3LGrVqsWkSZO4/vrr\nadeuHbm5uRphIzu1fDncwo3kMZu+TOI+rgSM5csTcLFjj4Wbb4bHHgujcPSEdHzF0jEP5LDzG6oP\nAf0rbC8EmlR2zphuqGawqVOneq9evar1mvr+S98DZvgWzB9gkIdB7eGjRYsEXnTkyHCRHj3c161L\n4IXSA3G8oVqZycD5FnQC1nk8+ttFpNoNvNSZWeN4fstd2/bVrQu33ZbAi15xBTz5ZBgfP3FiAi+U\nWSq9oWpmTwPdgUZmVgjcBGQDuPuDwBTgNMJQyGJgQKLCZpLu3bvTvXv3qGNIhjnpluMZf/g0Gg2H\n4uVw0EGhsO/xzdTK5OeHkTht2oRt9/+Mk5cqiWW0TP9K3nfg8ngFcndNYhUBL3/gSTLUyy/DzJlw\n003k59dKfDHfkbZtw+cPPoChQ+G556BxpetAy04k1fijOnXqsHbtWhWaaubl87nXqVMn6igShbVr\nw4iVyZNDizlqmzaFMfW9e8P330edJmUl1dwyzZo1o7CwkGQcSZPutq7EJBno8sthzRqYMgUqPCsR\nmS5dYMIEOPNMOOcceOEFqJlUpSolJNV3LDs7WysBiVSnCRPC06e33lr1p08ToU+f8MDT4MHh4+GH\n1Qe/m5KquItINVq/PrTajz02PDWabAYNgpUrw1OsxcVQ4fkSqZyKu0im2mefcCN1//2Tt9vjD3+A\nzZtDd5FG0OyWpLqhKiLVZOuN044doVWraLPsilko7OvWhQVA/v73qBOlDBV3kUx0ww2h2yMZRsfE\nomZN+O47OPdc+OijqNOkBBV3kUyzalVYUGPTptTp5qhXL7TaGzSAX/4Svvoq6kRJT8VdJNPccQeU\nlMCNN0adZPcceGAo8GvWhGGSP/wQdaKkpuIukklWroQHH4Tzz4dDD406ze772c/CLJKLF8OSJVGn\nSWoq7iKZ5M9/hi1b4Pe/jzpJ1Z19Nnz2GRx+eNRJkpqKu0gm+c1v4IEH4OCDo06yZ+rXh7IyPvmf\nGznvgNeoUSMsDTh+fNTBkoeKu0gmadMGLrkk6hRxMeGvG7HJf2fk6nM41D9l2bKwRKAKfKDiLpIJ\nli+Hfv1g6dKok8TNsFvq0dsnU0pNJvNL9uVbiouJ75KAKUzFXSQT3HYb/O1vabUQ9fLlsIwcfsVz\nHMJinqY/NdiSmCUBU1D6/JcWkR1buhTGjoVLLw2rb6SJrf+UtzieyxnFybzGccxMp3/iHlFxF0l3\n994bPg8bFm2OOLvttrAEIMDDDOQoPqGgbrfELgmYQlTcRdLZhg2h1X722ZBm8/Xn58OYMdCiRXjQ\ntrhFG8aMgfwGL8O770YdL3JJOhWciMTFpk3w61/DBRdEnSQh8vO3W9+1pASOHBomGisoSLtfaLtD\nLXeRdNa4MYwaFWZ/zATZ2eHGcXFxWPCjuDjqRJFRcRdJVx98EBa9TpWZH+OlTRt46in48EO46KLM\n+/eXU3EXSVc33gh9+4auikzTuzfcfntYQnDixKjTREJ97iLp6LPPwoLXN98MtWpFnSYa110Xpln4\n1a+iThIJtdxF0tH994f+50GDok4SHTM466zw4NayZfDKK1EnqlYq7iLpZv16+Otf4ZxzwhzoAldf\nDWecAW+/HXWSaqPiLpJuPvww3ES88sqokySPMWPCI62nnw7z5kWdplqouIukm27dwlJ6HTpEnSR5\nNGoUumVq14aePcOiJWlOxV0knaxbF1rte+8ddZLk07JluMn87bcwdGjUaRJOo2VE0kn//lBWlnE3\nD2PWvn343rRuHXWShIup5W5mPc1soZktMrP/mn3IzPY1s3+Y2b/NbK6ZDYh/VBHZpU8/hZdfhi5d\nok6S3Lp0gYYNw/j/K64gXecIrrS4m1kWMAo4FWgD9DezNtsddjkwz93bAd2Bv5hZhg6uFYnI6NFh\n+OPAgVEnSQ2ffQZPPAFdu8L8+VGnibtYWu4dgUXu/rm7bwYmAH22O8aB+mZmwN7A10BpXJOKyM5t\n3AjjxoUHdjT8MTZt2sD06aEF//Ofw6xZUSeKq1iKe1NgRYXtwvJ9Fd0PHAF8AXwCXOXuZXFJKCKV\ne+45+OabsCCHxK5duzD/Tv36cMIJ8Oabib3ed9+F61WDeI2WOQX4CPgpkAvcb2b7bH+QmQ00swIz\nKygqKorTpUWE00+Hxx6D7t2jTpJ6Dj00PNx0xBFQM4FjTJYuDf39p50GX3+duOuUi6W4rwSaV9hu\nVr6vogHA8x4sApYAh29/Incf4+557p7XuHHjqmYWke3tu2+Ysz2N1kitVj/9KfzrX3D88WF79Oj4\n32i9805YsQImTYIGDeJ77h2I5SdhFtDKzFqW3yTtB0ze7pjlwC8AzOwAoDXweTyDishO3H8/PPxw\n1ClSn1n4/OWXYdKxNm3CEoVbtuzZedevD5/vuissIHLyyXt2vhhVWtzdvRQYArwKzAcmuvtcMxts\nZoPLD7sF6GJmnwBvANe7+5pEhRaRcj/8AH/4A7z6atRJ0seBB8KcOaEVP3QodO4M//737p9n61DL\nY48NBX6vveCQQ+Kfdydi6mBy9ynAlO32PVjh9RdA9fw6EpH/eOEFWLNGwx/jLScHXnopzAd/1VVh\nuOSKFbD//uEXau3aO//aFSvgrbfCfDbTp8M110C9etUWfSs9oSqSysaMCYXoxBOjTpJ+zKBfv9CN\n8s47obAD5OaG5wm6dQut+8MOC8X70EPDpGRt24bj9tsvzM554YWRxNfdF5FUtWhRGLp3ySW6kZpI\nDRqElZ0gTO3w61+HrpuxY+Hss0Ox/7//C+8ffjjcd19Y4nDNmsgKO4B5ROsL5uXleUFBQSTXFkkL\nb78NQ4aE7oOf/jTqNJmnpCQU8UWLoFOnautPN7PZ7p5X6XEq7iIiqSPW4q6/5URS0dKl4WlHkZ1Q\ncRdJRYMHhyF2Ef3lLclPxV0k1SxdCq+9FhZ/3vrgjch2VNxFUs2jj4aiftFFUSeRJKbiLpJKSkvD\nELyePcOCzyI7oeIukkrefBO++EJT+0ql9ISqSCo56SSYMSOMqxbZBRV3kVRiFlYNEqmEumVEUsX9\n94dZBvd0ClrJCGq5i6SCsjK4555wEzUrK+o0kgLUchdJBdOmweef60aqxEzFXSQVPPJImHL2zDOj\nTiIpQsVdJNmtXQvPPRemmq1TJ+o0kiJU3EWS3XffwRlnhHnbRWKkG6oiya5FC5gwIeoUkmLUchdJ\nZosXw/z5UaeQFKTiLpLMbr8dOnSA4uKok0iKUXEXSVYbNoTumHPOgbp1o04jKUbFXSRZTZgA33+v\nse1SJSruIsnqkUegbduw4pLIblJxF0lGy5bBBx+E4Y9abUmqQEMhRZJRixawfDnsvXfUSSRFqbiL\nJBv30Fpv0iTqJJLC1C0jkmzuuw969AhPpopUkYq7SDJxh9GjYeNGdcnIHlG3jEgymToVFi6Exx+P\nOomkuJha7mbW08wWmtkiMxu2k2O6m9lHZjbXzKbHN6ZIhhg9Gho0gLPPjjqJpLhKW+5mlgWMAk4C\nCoFZZjbZ3edVOGY/YDTQ092Xm9lPEhVYJG2tXAkvvADXXKOpfWWPxdJy7wgscvfP3X0zMAHos90x\n5wLPu/tyAHdfHd+YIhlgr73gpptg8OCok0gaiKW4NwVWVNguLN9X0WHA/mY2zcxmm9n5OzqRmQ00\nswIzKygqKqpaYpF01aAB3HgjHHxw1EkkDcRrtExN4BigF3AKcKOZHbb9Qe4+xt3z3D2vcePGcbq0\nSBqYMQMmTYItW6JOImkiltEyK4HmFbable+rqBBY6+7fA9+b2QygHfBpXFKKpLs//hE++yysuCQS\nB7G03GcBrcyspZnVAvoBk7c75u/AcWZW08zqAscCWmFAJBYLFsAbb8CgQZCVFXUaSROVttzdvdTM\nhgCvAlnAWHefa2aDy99/0N3nm9krwMdAGfCIu89JZHCRtPHgg5CdDRdfHHUSSSPm7pFcOC8vzwsK\nCiK5tkjS+P57aNoUTjsNnnoq6jSSAsxstrvnVXacph8QidKnn0K9ejBkSNRJJM1o+gGRKLVvD0uW\nQK1aUSeRNKOWu0hUPv8cSkpU2CUhVNxFolBWBr17w//8T9RJJE2puItEYfJkmD8f8vOjTiJpSsVd\npLq5w+23Q8uWmv1REkY3VEWq27Rp8P77YXrfmvpfUBJDLXeR6vbYY3DAATBgQNRJJI2p2SBS3R59\nNMwjoznbJYHUchepTqWloSvmiCOiTiJpTsVdJMHGj4ecHGhtn/JVnYN4/fdahVIST8VdJIHGj4eB\nA2HZMvgtd7LPlm8YePfhjB8fdTJJdyruIgk0fDgUF8NPWckFPM5YLmLpxgMYPjzqZJLuVNxFEmj5\n8vD5Zm7GcO7itz/aL5IoKu4iCXTQQXA487mYRxnJlSyl5bb9Iomk4i6SQLfdBsv3Opy+TOKP/D8A\n6tYN+0USScVdJIHyzyllzMPGBy3OZIPtS4sWMGaMppSRxFNxF0mUDRvgiCPIL3uCpUvDRJBLl6qw\nS/VQcRdJlFtvhUWLoHXrqJNIBlJxF0mETz+Fe+4J88d07Bh1GslAKu4iiXD11bDXXmFqX5EIaOIw\nkXgrKIApU+AvfwmzP4pEQMVdJN7y8mDGDOjUKeokksHULSMST6tWhc8//zlkZ0ebRTKairtIvMyY\nEZbOmzw56iQiKu4icbF6NfTrF+YV6N496jQi6nMX2WNbtsC558I338Arr8A++0SdSETFXWSP/fGP\n8MYbMHYsHH101GlEAHXLiOy5kpLwsJIWvJYkElNxN7OeZrbQzBaZ2bBdHNfBzErNrG/8IookuT/9\nKSx6LZJEKi3uZpYFjAJOBdoA/c2szU6OuwN4Ld4hRZJOSQmcfTbMnBm2zaLNI7KdWFruHYFF7v65\nu28GJgB9dnDcFcBzwOo45hNJPu5w3XXw7LOwcmXUaUR2KJbi3hRYUWG7sHzfNmbWFDgDeGBXJzKz\ngWZWYGYFRUVFu5tVJHrucOONMGIEXHklnHNO1IlEdiheN1RHANe7e9muDnL3Me6e5+55jRs3jtOl\nRaqJe1jx+rbb4NJLw6yPIkkqlqGQK4HmFbable+rKA+YYKHfsRFwmpmVuvsLcUkpkgxKS8OkYIMG\nwejRUEODzSR5xVLcZwGtzKwloaj3A86teIC7t9z62sweA15UYZe04Q4bN4bFTydPhlq1VNgl6VX6\nE+rupcAQ4FVgPjDR3eea2WAzG5zogCKR2nrztEcP+P57qFNHhV1SQkxPqLr7FGDKdvse3MmxF+55\nLJEkUFYGv/sd3H03XH55aLmLpAhNPyCyI199BeedB6+/DldcAffeq7HsklJU3EV25KyzYNYsGDMG\nLrlEhV1Sjoq7yFalpWGGx9q1YeRIyMqCo46KOpVIlejOkAiEJ01/8YuwsDVAbq4Ku6Q0FXfJbFu2\nhEm/cnNh9mzo3DnqRCJxoeIumaugANq3D33qrVqF4n7eeVGnEokL9blL5ikrC2PV69WDH36AiROh\nb1/dNJW0ouIumaOwEG65Bdavh6efhiOOgPnz9VCSpCX9VEv6e/996N8fcnLCUngHHBBa76DCLmlL\nLXdJbyNGhBEw++wDV10VHkjKyYk6lUjCqbhLeikqgnHjoFMn6NoV+pSvK3PRRaHAi2QI/U0qKWn8\n+NAAr1EDWrYo4583vAH9+kHTpvDb34bZGwFatoShQ1XYJeOo5S4pZ/x4GDgQiosBnKeXd6HTn//F\nD/X2p/Zll4WFNNq2jTqmSKTUcpfUUlbGS9e8wR3FQzDKAOOvDCCfJzm64Rehj12FXUQtd0kRa9bA\n44/DQw/x1OrPWEsD7uUqFtGKMQwCwFZUcg6RDKKWuyS/GTP+05d+wAFc1fBJmrKSRbT60WEHHRRR\nPpEkpOIuyWfTptBKnzgxbHfoEBbL+OQTeOstOt6bT1bdOj/6krp1w7rVIhKouEvyWLYMbrgBmjWD\nCy+EJ54I+/faK6yGdOSRAOTnh2nWW7QIMwa0aBG28/Ojiy6SbNTnLslh+HD485/D6z59YMiQsG7p\nTuTnq5iL7Ipa7hKNzZvhySfh22/Ddvv2oU/988/h+efhhBM0kZfIHlBxl+pVVAS33hr6Us47D555\nJuzv2xfuuCPsF5E9pm4ZqR6bNoW5XcaNC6979gxPjp50UtTJRNKSWu6SOO7w2Wfhde3asGBBaK3P\nnQsvvwynnKJZGUUSRC13ib+SktDdcvfdoaCvWAENG8LUqSrmItVE/6dJ/KxbB3fdBQcfHFromzbB\nyJFhxSNQYRepRmq5y55zDyNbFi6E3/0uDGF86KHQr66CLhIJFXepuo8+Ci31+vXhgQegY0eYNy8s\nXycikVKzSnaPO7z2Whjl0r49vPAC7Lvvf95XYRdJCirusnuGDw+jXObOhdtvDzdLtz5ZKiJJI6bi\nbmY9zWyhmS0ys2E7eD/fzD42s0/M7B0zaxf/qBKJ9evhL3+Bjz8O2/n5YZHpJUtg2DDYf/9o84nI\nDlVa3M0sCxgFnAq0AfqbWZvtDlsCdHP3o4BbgDHxDiqJVXHZupwceH5kYbg52rz5j5eta9sWBgwI\n49ZFJGnFckO1I7DI3T8HMLMJQB9g3tYD3P2dCse/BzSLZ0hJrO2XrfvfZYM4/aq/UlbDqXH2WXDt\ntZCXF3VMEdkNsXTLNAUqrnFTWL5vZy4GXt6TUFK9hv+vk1v8dvmW8T31uJ8hHN9kETz9tAq7SAqK\n61BIM+tBKO7H7eT9gcBAgIO0bE70fvgBxo/nxeV3cyRzOZb3eJ9juYZ7ALAvIs4nIlUWS8t9JdC8\nwnaz8n0/YmZHA48Afdx97Y5O5O5j3D3P3fMaN25clbwSD+vXh2WLcnLg4ovJys7ifB7nQ9r/6DD9\n/hVJXbEU91lAKzNraWa1gH7A5IoHmNlBwPPAee7+afxjSlxs2hQ+l5aGYYy5ufD663ww9iOeq3s+\nJdTadqiWrRNJbZV2y7h7qZkNAV4FsoCx7j7XzAaXv/8g8P+AhsBoCwsslLq7OmqTgTtMmxYm8frq\nK/jXv6BBg7Aoxk9+AkA+gIUh7MuXhxb7bbdppSORVGbuHsmF8/LyvKCgIJJrZ4TNm2HCBLjnnjBN\nQOPGcNlloYJnZ0edTkSqyMxmx9J41twy6eqhh+DKK6FNG3jkkdAMr1Mn6lQiUk1U3NPFvHkwYgR0\n7w7nngvnnw+HHQYnn6y1SEUykIp7KisrC5N43XNP+FynTphLHcJkXqecEm0+EYmMinsq69MHXnwR\nDjwQbrkFBg+GRo2iTiUiSUCzQqaSwkK46SbYuDFsX3ABPPEELFsGv/+9CruIbKOWeyp4773Qnz5p\nUhjaeNxxYT71vn2jTiYiSUot92T21VfQqRN07gyvvAJDh8LixaGwi4jsglruyWbNmjB3+gknhLHp\njRvD/feHLpi99446nYikCBX3ZPHJJ3DvvWH+3b32glWrwpzp//hH1MlEJAWpWyZq774bWulHHw1P\nPRVa6G+9pcUwRGSPqOUehXXrwuRdDRvCd9/BokVwxx1wySVh3hcRkT2klnsCbb903eS/fBamBGjW\nDP70p3DQiSeGSbyuu06FXUTiRi33BKm4dN0v+CdXL7uHXr+dwpasbLLO7fefKRfNoKb+M4hIfKmq\nJMjN/7uZ4uIwP/rljCKPAm7mJl5qMphZ4w6MOJ2IpDsV93hbtgxGjeLd5WPpxHss5lAuYzRf04DN\n1Mb+aw0rEZH4U3GPB3eYOTMMZfzb38CM9+qeSY3iMgC+pMm2Q7V0nYhUB91QjYcvvghT7U6dCr/7\nHSxZwroxE1lZ97AfHaal60SkuqjlXhVffgkPPABLl8Ljj0PTpjBlCvz856GC85/7pVq6TkSioOK+\nO2bPDhN4PfMMlJRA795hObtatXY4d3p+voq5iERD3TKxeuAByMuDF16A3/wGPv00TA1Qq1bUyURE\n/ota7jvzzTdh7dFjjgnTA5x+OvzwAwwYEFY5EhFJYmq5b2/BArjssvAU6XXXhal2IWwPHarCLiIp\nQS33ii64AMaNC10t+flw1VXQrl3UqUREdltmF/fi4rC6UX4+ZGVB+/ZwyCFhLdKf/CTqdCIiVZaZ\nxf2LL2DUKHjoIVi7NiwwffLJodtFRCQNZFaf+5o1cP75YYrG228P49KnTdOydSKSdtK/5b5lS5jv\n5eCDoX79sNj0b34Tpt495JCo04mIJET6FvfvvoPHHgsPHZWUhIWla9eG+fND/7qISBpLv26ZlSth\n2DBo3hyuuCIsMH3XXWHedFBhF5GMEFNxN7OeZrbQzBaZ2bAdvG9mNrL8/Y/N7Gfxj1qJsjADI9On\nw513hn70d94Ja5SedZaKuohklEqLu5llAaOAU4E2QH8za7PdYacCrco/BgIPxDnnjpWVwYsvQo8e\nYQ1SCIV88WKYOBE6d66WGCIiySaWlntHYJG7f+7um4EJQJ/tjukDjPPgPWA/M2uy/YniZuNGGDMG\n2rYN0wIsWhS6XwCys8NoGBGRDBbLDdWmwIoK24XAsTEc0xRYtUfpduass+Cll8JDR+PHh+3s7IRc\nSkQkFVXraBkzG0jotuGgPVmS6IYb4NprwwIZW2+UiojINrEU95VA8wrbzcr37e4xuPsYYAxAXl6e\n71bSirp2rfKXiohkglj63GcBrcyspZnVAvoBk7c7ZjJwfvmomU7AOndPTJeMiIhUqtKWu7uXmtkQ\n4FUgCxjr7nPNbHD5+w8CU4DTgEVAMTAgcZFFRKQyMfW5u/sUQgGvuO/BCq8duDy+0UREpKrS7wlV\nERFRcRcRSUcq7iIiaUjFXUQkDam4i4ikIQsDXSK4sFkRsKyKX94IWBPHOImWSnlTKSukVt5Uygqp\nlTeVssKe5W3h7o0rOyiy4r4nzKzA3fOizhGrVMqbSlkhtfKmUlZIrbyplBWqJ6+6ZURE0pCKu4hI\nGkrV4j4RMrSwAAADHElEQVQm6gC7KZXyplJWSK28qZQVUitvKmWFasibkn3uIiKya6nachcRkV1I\n2eJuZmeZ2VwzKzOzpLxLXtnC4snEzMaa2WozmxN1lsqYWXMzm2pm88p/Bq6KOtOumFkdM3vfzP5d\nnvcPUWeqjJllmdmHZvZi1FkqY2ZLzewTM/vIzAqizrMrZrafmU0yswVmNt/MErbQc8oWd2AOcCYw\nI+ogOxLjwuLJ5DGgZ9QhYlQKXOvubYBOwOVJ/r39ATjB3dsBuUDP8nUPktlVwPyoQ+yGHu6emwLD\nIe8FXnH3w4F2JPB7nLLF3d3nu/vCqHPsQiwLiycNd58BfB11jli4+yp3/6D89QbC/yBNo021c+UL\nx39Xvpld/pG0N7vMrBnQC3gk6izpxMz2BY4HHgVw983u/m2irpeyxT0F7GzRcIkjM8sB2gP/ijbJ\nrpV3c3wErAZed/dkzjsCuA4oizpIjBz4p5nNLl+nOVm1BIqAv5Z3eT1iZvUSdbGkLu5m9k8zm7OD\nj6RtAUv1MbO9geeAoe6+Puo8u+LuW9w9l7C+cEczOzLqTDtiZr2B1e4+O+osu+G48u/tqYQuuuOj\nDrQTNYGfAQ+4e3vgeyBh9+JiWokpKu5+YtQZ9kBMi4ZL1ZhZNqGwj3f356POEyt3/9bMphLubyTj\nzeuuwC/N7DSgDrCPmT3p7r+OONdOufvK8s+rzexvhC7RZLwXVwgUVvirbRIJLO5J3XJPcbEsLC5V\nYGZG6Lec7+53R52nMmbW2Mz2K3+9F3ASsCDaVDvm7je4ezN3zyH8zL6ZzIXdzOqZWf2tr4GTSc5f\nmrj7l8AKM2tdvusXwLxEXS9li7uZnWFmhUBn4CUzezXqTBW5eymwdWHx+cBEd58bbaqdM7OngXeB\n1mZWaGYXR51pF7oC5wEnlA9/+6i8pZmsmgBTzexjwi/919096YcYpogDgJlm9m/gfeAld38l4ky7\ncgUwvvxnIRf4U6IupCdURUTSUMq23EVEZOdU3EVE0pCKu4hIGlJxFxFJQyruIiJpSMVdRCQNqbiL\niKQhFXcRkTT0/wFk/KIDVdTySwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f6568be48>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "xm = np.array([0,1,2,3,4,5])\n",
    "ym = np.array([0.1,0.2,0.3,0.5,1.0,0.9])\n",
    "\n",
    "m = GEKKO()             # create GEKKO model\n",
    "m.options.IMODE = 2     # solution mode\n",
    "x = m.Param(value=np.linspace(-1,6)) # prediction points\n",
    "y = m.Var()             # prediction results\n",
    "m.cspline(x, y, xm, ym) # cubic spline\n",
    "m.solve(disp=False)     # solve\n",
    "\n",
    "# create plot\n",
    "plt.plot(xm,ym,'bo')\n",
    "plt.plot(x.value,y.value,'r--',label='cubic spline')\n",
    "plt.legend(loc='best')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5: Linear and Polynomial Regression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x15f65c32748>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYwAAAEKCAYAAAAB0GKPAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xdc1WX7wPHPDRxEVNyYiRPNDYporoYNR7Y0K00tLaMc\nDbOnbPjL6qmn5WOP2TItTduustTS0jSt3OJMQXHvAQiIwLl+f9xMRT0oh8O43q/XeXG+65zrUJ6L\n7z2u24gISiml1MV4eToApZRSRYMmDKWUUi7RhKGUUsolmjCUUkq5RBOGUkopl2jCUEop5RJNGEop\npVyiCUMppZRLNGEopZRyiY+nA8hPVapUkTp16ng6DKWUKjJWr159VESqunJusUoYderUYdWqVZ4O\nQymligxjzC5Xz9UmKaWUUi7RhKGUUsolmjCUUkq5pFj1YeQmJSWFvXv3cvr0aU+HUiz4+fkRFBSE\nw+HwdChKlWjR0dGMGTOGadOmcerUKcqWLUu/fv0YMWIEwcHBbnlPU5zWwwgPD5ezO7137txJuXLl\nqFy5MsYYD0VWPIgIx44dIz4+nrp163o6HKVKrHnz5tGrVy9SUlJISUnJ3O9wOHA4HEyfPp1u3bq5\n9FrGmNUiEu7KuW5rkjLG1DTGLDLGbDbGbDLGPJHLOcYYM84YE2WMiTTGhGU71tUY80/6sZGXGsfp\n06c1WeQTYwyVK1fWuzWlPCg6OppevXqRmJiYI1mAbVFJTEykV69eREdH5/t7u7MPIxUYISJNgLbA\nUGNMk7PO6QY0SH9EAB8CGGO8gffTjzcB+uRyrcs0WeQf/V0q5Vljxow5J1GcLSUlhbFjx+b7e7st\nYYjIARFZk/48HtgC1DjrtDuAz8X6C6hgjKkOtAGiRGSHiJwBvk4/162io6MZMmQIAQEBeHl5ERAQ\nwJAhQ9ySqZVS6lJMmzYtZ8LwPveclJQUpk6dmu/vXSCjpIwxdYCWwN9nHaoB7Mm2vTd93/n25/ba\nEcaYVcaYVUeOHLnkGOfNm0dISAgTJ04kPj4eESE+Pp6JEycSEhLCvHnzLvm1vb29adGiBU2bNiU0\nNJQxY8bgdDoveE1MTAxffvnlJb+nUqp4OnXqVM4dlYDagLnIefnA7QnDGFMWmAE8KSJx+f36IjJB\nRMJFJLxqVZdmt5/D3W2CpUuXZt26dWzatIkFCxYwb948Xn755QteowlDKZWbsmXLAnAd4AdwBNgF\nSO7n5Se3JgxjjAObLL4QkZm5nLIPqJltOyh93/n2u0VBtgkGBgYyYcIExo8fj4gQExPDNddcQ1hY\nGGFhYSxfvhyAkSNHsnTpUlq0aMHYsWPPe55SqmTp168fzXx8+LI0NH4QGjQ79xyHw0H//v3z/81F\nxC0P7A3S58C7FzinOzAv/dy2wIr0/T7ADqAu4AusB5pe7D1btWolZ9u8efM5+85Wrlw5webnCz4C\nAgIu+lq5KVOmzDn7ypcvLwcPHpSEhARJSkoSEZFt27ZJxmdYtGiRdO/ePfP8853nCa78TpVS7hH1\nzz/yl5eXvHQ9wmjk6n7nflf5+/tLVFSUS68HrBIXv9fdOXGvA9Af2GCMWZe+73mgFoCIfATMBW4B\nooBEYGD6sVRjzDDgZ2yXzqcissldgbra1ueONsGUlBSGDRvGunXr8Pb2Ztu2bZd1nlKqeAv+/nuC\nnU4qboCY8rB0bdax7PMw3DF5z20JQ0T+4JxumHPOEWDoeY7NxSYUtytbtizx8fEunZcfduzYgbe3\nN4GBgbz88stUq1aN9evX43Q68fPzy/WasWPHunSeUqoY27wZRo0C4Kpj0OtAG2ad3IqXl53p3b9/\nf4YPH+62md7FvjSIK/r168fEiRMv2I+RX22CR44c4dFHH2XYsGEYY4iNjSUoKAgvLy+mTJlCWloa\nAOXKlcuRxM53nlKqhEhNhQceINGZzPUPw/3HazL4i9+JLVVwfzxq8UFgxIgRF62N5HA4GD58+CW9\nflJSUuaw2ptuuonOnTvz0ksvATBkyBCmTJlCaGgoW7dupUyZMgCEhITg7e1NaGgoY8eOPe95SqkS\n4o03YNUqJrSClTVgyrUBePmWKtAQin0tqS1bttC4ceOLXpuftVmKO1d/p0qpfJKSAq1awYYNHCoD\n74y8lht7P0fX+l0v+6ULRS2poqZbt25ERkYSERGRY6Z3REQEkZGRmiyUUp7jcMDff+Mc/iTVQtvz\n9shf8yVZ5JX2YWQTHBzM+PHjGT9+vKdDUUqpHE47DOH1F9Crew+eI41SHvj61jsMpZQqrNasgU12\nRsHkdZPZdGQTs7fPwdfb1yPh6B2GUkoVRomJ0KcP7NoF//43fYcMIi45jmaBzTxWNVoThlJKFUYj\nR0L6BN0z/36Zcr1780yHZzwakjZJKaVUYbNgAbz3HgBJPtDoaT8ei3yTxJREj4alCaMA5DZD/KOP\nPuLzzz/3QDRKqULtxAkYODBzc2r/EHamHeWPPX/g5+PZCg/aJOUhjz76qFtfP6NYmJeX/k2gVJEy\ndCjsSy/OXbUqA1+bi8/Bn6lVvhZexrP/nvXbxENGjx7NO++8A8D111/Ps88+S5s2bbjqqqtYunQp\nAGlpafzrX/+idevWhISE8PHHHwO2COKNN95IWFgYzZs35/vvvwfsGhoNGzbk/vvvp1mzZuzZsyf3\nN1dKFU7ffANffZW5GfvRuziq1+DBlg9yU72bPBiYVeIShjHnPiIiLv14fklNTWXFihW8++67mYsr\nTZo0ifLly7Ny5UpWrlzJJ598ws6dO/Hz82PWrFmsWbOGRYsWMWLEiIxy8Wzfvp0hQ4awadMmateu\nnX8BKqXcb+XKzKenHuxHwx1P0Xt6b06dyf9K2ZdCm6QKiZ49ewLQqlUrYmJiAPjll1+IjIxk+vTp\ngC1AuH37doKCgnj++edZsmQJXl5e7Nu3j0OHDgFQu3Zt2rZt65HPoJS6TO+8Ax07wuuv8/WDbTi0\ncBoxJ2Mo4ygcteNKXMK4WOmsyz1+qUqVskXEvL29SU1NTX8v4b333qNLly45zp08eTJHjhxh9erV\nOBwO6tSpw+nTpwG0KKFSRd2dd8Idd/AQEFilNlX9q3ps3sXZ3NYkZYz51Bhz2Biz8TzH/2WMWZf+\n2GiMSTPGVEo/FmOM2ZB+bFVu15cEXbp04cMPP8wshrht2zYSEhKIjY0lMDAQh8PBokWL2LVrl4cj\nVUpdso0bYcKEHH+N7ordjTGG2xveTrua7TwYXE7uvMOYDIzHLtN6DhF5G3gbwBhzGzBcRI5nO6WT\niBx1Y3wFJjExkaCgoMztp556yqXrBg0aRExMDGFhYYgIVatWZfbs2fTt25fbbruN5s2bEx4eTqNG\njdwVulLKnU6fhvvugw0b4McfYeJEDvkLTT9oStugtszpM4fSjtKejjKTO1fcW2KMqePi6X2Ary56\nVhHldDoveHzx4sWZz6tUqZLZh+Hl5cXrr7/O66+/fs41f/75Z66vtXFjrjd0SqnC6PnnbbIAO1nv\n2DFm715CQkoC/g7/QpUsoBD0YRhj/IGuwLBsuwVYaIxJAz4WkQkeCU4ppdzll19g7Nis7TFjoHFj\nHqExzas1p6JfRc/Fdh4eTxjAbcCys5qjOorIPmNMILDAGLNVRJbkdrExJgKIAKhVq5b7o1VKqct1\n9Cg88EDWdvfuMHgwf+39izY12tC+ZnvPxXYBhWEeRm/Oao4SkX3pPw8Ds4A257tYRCaISLiIhFet\nWtWtgSql1GUTgUGD4OBBux0YCJ9+yqYjm+nwaQfaTWpHqjPVszGeh0cThjGmPHAd8H22fWWMMeUy\nngOdAW2YV0oVDx9/DN9/n7X92WcQGMjvu34HILx6OD5ehaHx51xui8oY8xVwPVDFGLMXeAlwAIjI\nR+mn9QB+EZGEbJdWA2aljzv2Ab4UkfnuilMppQpU5coQEABxcTBsGNxyCwBDWg/hutrXUcW/iocD\nPD93jpLq48I5k7HDb7Pv2wGEuicqpZTysLvvhtat4dVX4e23ERG+2fQNPRr1oGlgU09Hd0GFoQ+j\n2Nu7dy933HEHDRo0oF69egwbNozk5OTLft3Fixdz66235umamJgYvvzyy8ztVatW8fjjj192LEqp\nPKhTByZNAj8/5mybQ58Zfbjms2sya8IVVpow3ExE6NmzJ3feeSfbt29n+/btJCUl8cwz7ls5K6O0\nSG7OThjh4eGMGzfObbEopYCffrJ3FidOnHNod+xu/Hz86Nu8b6EpAXI+mjDc7LfffsPPz4+B6Qui\neHt7M3bsWD7//HPGjx/PsGFZ009uvfXWzEl8gwcPJjw8nKZNm/LSSy9lnjN//nwaNWpEWFgYM2fO\nzNw/evRo+vfvT4cOHejfvz8xMTFcc801hIWFERYWxvLlywEYOXIkS5cupUWLFowdOzbHXcqpU6cY\nOHAgzZs3JyQkhBkzZrj716NU8bd/PwwYANOnQ4sWEBmZ4/CwNsPYNmwbg1sP9kx8eVDyEsbo0bnX\nMM94XHll3s4fPfqCb7dp0yZatWqVY19AQAB16tS54J3Aa6+9xqpVq4iMjOT3338nMjKS06dP8/DD\nDzNnzhxWr17NwYxheek2b97MwoUL+eqrrwgMDGTBggWsWbOGb775JrPZ6Y033uCaa65h3bp1DB8+\nPMf1r776KuXLl2fDhg1ERkZyww03XPCzKaUuIi0N+ve38y4AUlMzv2Pik+N59fdXiUuOo2b5mvh6\n+3owUNcUzrFbim+//ZYJEyaQmprKgQMH2Lx5M06nk7p169KgQQMA+vXrx4QJWZPgb7/9dkqXtqUE\nUlJSGDZsGOvWrcPb25tt6YvJX8jChQv5+uuvM7crVix8M02VKlLeegt++80+NwamTYMqdhTU28vf\n5tUlr7Ji/wrm9JnjwSBdpwnDzZo0aZK5nkWGuLg4Dh48SOXKlXN8kWeUKN+5cyfvvPMOK1eupGLF\nigwYMCDz2IVkL20+duxYqlWrxvr163E6nfj5eXYtYKVKnOXLYdSorO0XXoBOnTI3q5WpRkW/iozs\nMNIDwV2aktkkJXL+x/79eTv/Ik1SN954I4mJiXz+uS3am5aWxogRIxg2bBh169Zl3bp1OJ1O9uzZ\nw4oVKwCbUMqUKUP58uU5dOgQ8+bNA6BRo0bExMQQHR0NwFdfnb9eY2xsLNWrV8fLy4upU6eSlpYG\nQLly5YiPj8/1mptvvpn3338/c/tELh10SikXHD8OffrYJimAdu0gW18kwNA2Q9k9fDcdanXwQICX\npuQljAJmjGHWrFlMnz6dBg0aULlyZby8vHjhhRfo0KEDdevWpUmTJjz++OOEhYUBEBoaSsuWLWnU\nqBH33XcfHTrY/6H8/PyYMGEC3bt3JywsjMDAwPO+75AhQ5gyZQqhoaFs3bo18+4jJCQEb29vQkND\nGZu98Bnw4osvcuLECZo1a0ZoaCiLFi1y029FqWLuySdh9277vEIFu063j23QWXNgDRFzIjh06hBl\nfct6MMhLICLF5tGqVSs52+bNm8/Z50nLli2TWrVqyerVqz0dyiUrbL9TpQqd6GiR8HDbDjFrVuZu\np9Mp1352rTAaeXbBsx4MMAuwSlz8jtU+jALWvn17XSFPqeKuXj1YtszOv7jzzhyHBrUcRFxyHCM7\nFp2+iwyaMJRSKj/Exdk+i4zRhb6+0KNH5mERwRhD/9D+9AvpV+gn6eVG+zCUUupyicDDD0PLlvD3\n37meMubPMdz17V1EH48ukskCNGEopdTl+/hj+PZb2LULOnaE7dtzHD6edJxXfn+FmVtmEnU8ykNB\nXj5tklJKqcuxdq0dFZXhoYcgfXJthkqlK/FNr2/4OfpnutTvUsAB5h9NGEopdaliY21RwYzq0yEh\nOdfpxt5dVPSrSLcG3ejWoJsHgsw/2iRVAA4ePEjv3r0JDg6mVatW3HLLLRcs1VGnTh2OZtSeyeaj\njz7KnAColPIwEXs3kT6RlrJl4bvvIL08D4BTnHT7ohudpnRid+xuDwWaf9y54t6nwK3AYRFplsvx\n67FLs+5M3zVTRF5JP9YV+B/gDUwUkTfcFae7iQg9evTggQceyKzTtH79eg4dOsRVV12Vp9d69NFH\n3RGiUupSvPceZK/oPHEinPVvevme5azYt4LqZatT0a/o12Zz5x3GZKDrRc5ZKiIt0h8ZycIbeB/o\nBjQB+hhjmrgxTrdatGgRDocjx5d9aGgoaWlpORY/GjZsGJMnT87cfuutt2jevDlt2rQhKsp2ko0e\nPZp33nkHgKioKG666SZCQ0MJCwvLLBeilCoATqctV55h6FC4995zTutYqyPLH1zOxNsnUq5UuQIM\n0D3cljBEZAlw/BIubQNEicgOETkDfA3ckV9xmZcN5mXD6v2rAYiYE4F52RAxJwKA1ftXZ56TodWE\nVpiXDRNW28qwE1ZPwLxsaDWh1blvcJaNGzeeU97cFRllxocNG8aT2TvU0vXt25ehQ4eyfv16li9f\nTvXq1fP8HkqpS+TlBQsXwmOPQXg4jBlzzilLdi0h1ZlKu5rtuKXBLR4IMv95ug+jvTEm0hgzzxiT\nsZhtDWBPtnP2pu8rUfr06ZP5888//8xxLD4+nn379tEjfVKQn58f/v7+BR6jUiWary+MGwdLlkCp\nUjkOrTu4jk5TOtFuUjtS0lI8FGD+8+QoqTVALRE5ZYy5BZgNNLjINecwxkQAEQC1atW66PnyUs41\ncyfcNoEJt2WtKdHqylbnnLM6YnWO7YhWEUS0inApvqZNm55T3hzAx8cHp9OZuX12+fLsE3uK6iQf\npYqdceOgTRto2zZrX7ZO7gx/7/0bL+NFh5odcHg7CjBA9/LYHYaIxInIqfTncwGHMaYKsA+ome3U\noPR953udCSISLiLhVatWdWvMl+KGG24gOTk5x0JHkZGRiAibN28mOTmZkydP8uuvv+a47ptvvsn8\n2a5duxzHypUrR1BQELNnzwYgOTmZxMREN38SpUq4+fPtfItrr7Ud3iLnPfWR8EdY98g6Xr7+5QIM\n0P08ljCMMVeY9D+djTFt0mM5BqwEGhhj6hpjfIHewA+eivNyZZQ3X7hwIcHBwTRt2pTnnnuOK664\ngnvuuYdmzZpxzz330LJlyxzXnThxgpCQEP73v/+dU4YcYOrUqYwbN46QkBDat29/znKtSql8tHMn\n3HefTRIpKTB7tu34PsuxxGP8Z+l/OJ16mqaBTSnvV94DwbqPkQtkyct6YWO+Aq4HqgCHgJcAB4CI\nfGSMGQYMBlKBJOApEVmefu0twLvYYbWfishrrrxneHi4rFq1Kse+LVu20Lhx4/z4SCqd/k5ViXL6\nNHToAGvW2O0aNezzXNajefiHh5m4diIDWgzgszs+K+BAL40xZrWIhLtyrtv6MESkz0WOjwfGn+fY\nXGCuO+JSSqk8GTYsK1k4HHY4bS7JQkSoX6k+5UuV59kOzxZwkAXD06OklFKq8PrkE5g0KWt77Nic\nHd7ZGGN4tuOz7Bm+h0ZVGhVQgAWrRCQMdzW7lUT6u1QlRmSkvbvI0LcvDBmS66ljlo/hiXlPEJcc\nVywm6J1PsU8Yfn5+HDt2TL/o8oGIcOzYMfz8/DwdilLu16RJVsIIDYUJEyCXIe67Y3czatEoxq0Y\nx197/yrgIAtWsa9WGxQUxN69ezly5IinQykW/Pz8CAoK8nQYSrmfj4+dwd2mDbRuDeeZHBsUEMR/\nu/yXyEORdA7uXMBBFiy3jZLyhNxGSSmlVJ5s337OehbnczTxKFX8q7g5IPfKyyipYt8kpZRSLps6\nFRo3hv/+94IT8wCOJByh0fhGDJg9gKSUpAIK0LM0YSilFMDq1RARAWlpMGIEjM911H+mqZFTOZZ0\njL1xe/HzKRn9esW+D0MppS7q8GHo0cNO0gPb4T1gwAUvGd52ONXKVKNtUNsSU+9N7zCUUiXbmTPQ\nqxfsSS+SXb68Lf1RLvfhsbGnY5m9dTbGGPqG9CW4UnABButZmjCUUiXbE0/A0qX2uTHw5ZcX7PR+\n+pen6fFND0YvHl0w8RUimjCUUiXXRx/ZR4b//AduOf9iR2nONBJSEvD19uXepueusFfcaR+GUqrk\nyj4/q3dveOaZC57u7eXNl3d9SfTx6BLVFJVB7zCUUiXXqFG2mOA119iaURfovB7x8wgmr5uMiJTI\nZAF6h6GUKmmcTrsmd4a77oKePS+YLH6J/oX//vVffL19ua72ddStWLcAAi18NGEopUoOp9MmiLAw\nePHFrCRxkWGxbYPaMqjlIK6qfFWJTRagCUMpVZK8+KIdMjt7NmzcaEdEeXtf8JKDpw5yRdkr+OT2\nT0p8EVO39WEYYz41xhw2xmw8z/G+xphIY8wGY8xyY0xotmMx6fvXGWO0OJRS6vJNnWpHQWUICrpo\nsvhu03cEjwtm0hq7JkZJmaB3Pu7s9J4MdL3A8Z3AdSLSHHgVmHDW8U4i0sLVolhKKXVey5bBoEFZ\n2926wVtvXfASEeHdv98lMSWR5LRkNwdYNLhzidYlxpg6Fzi+PNvmX4DWzFZK5b+YGFv248wZu920\nKXz99UXvLowxLOi/gM/Wfsbg8MHuj7MIKCzDah8C5mXbFmChMWa1MSbiQhcaYyKMMauMMat0zQul\nVA6xsXDrrVnzLapUgTlzICDggpd9t+k7Nh3ehL/Dn6Fthpb4pqgMHu/0NsZ0wiaMjtl2dxSRfcaY\nQGCBMWariCzJ7XoRmUB6c1Z4eHjJ7pFSSuW0eDFs2WKf+/rCrFlQ98KjnDYf2cz9s+9HRNg8dDP1\nKtZzf5xFhEfvMIwxIcBE4A4ROZaxX0T2pf88DMwC2ngmQqVUkXbHHfDDD7aQ4KRJ0LHjxa8B6leq\nT5/mfTRZnMVjdxjGmFrATKC/iGzLtr8M4CUi8enPOwOveChMpVRR1707REVBYOBFT011ptKkahNW\nDFqBU5wFEFzR4s5htV8BfwINjTF7jTEPGWMeNcY8mn7K/wGVgQ/OGj5bDfjDGLMeWAH8JCLz3RWn\nUqqY+f57eOopuxBSBheSxU/bfiL0o1DWH1xPaUdpyviWcWOQRZM7R0n1ucjxQcCgXPbvAELPvUIp\npS5i5Uro0weSkmDHDvjiCyhz8S/+VGcqw+YNI+ZkDL9E/0LoFfoVlJvCMkpKKaUuT0wM3HabTRYA\nGzZAYqJLl/p4+TD3vrkMbT2UEe1HuC/GIk4ThlKq6DtxwvZVHDpktytWhLlzoWrVi146e+tsTp05\nReOqjRl/y3i8jH4tno/+ZpRSRVtysp2Yt3mz3fb1tbWiGja86KWLdi6i5zc9afNJG06nnnZzoEWf\nJgylVNHldMLAgfD771n7Jk+Ga6916fKjiUcp7SjNXY3vws/Hzz0xFiMen7inlFKXbP16uwBShjfe\nsJ3eF+EUJwbD3U3vJqx6GLUr1HZjkMWH3mEopYquli3hl1+gQgUYPPiiS6xm+L9F/0f/Wf05deYU\nwZWC8fHSv51dob8lpVTRdv31sHo11Kp10YWQADYc2sBrS1/Dy3gxOHwwHWp1cH+MxYQmDKVU0bJ0\nKUyZAh98YDu4Aeq5XsKjebXmfH7n5xxJPKLJIo80YSilio6NG+H22+HkSdizx/ZflCvn0qWJKYnM\n3jqbPs360D+0v5sDLZ60D0MpVTTs2gVduthkAbbD+9ixC1+TTkSImBNB35l9eWnxS24MsnjThKGU\nKvyOHrXJYv9+u12uHMybB3XquHR5mqRR2qc0ZRxluKfpPe6Ls5jThKGUKtxOnbKLIP3zj93OmJjX\nsqVLlyelJOHj5cMnt3/ChsEbaBbYzI3BFm+aMJRShVdyMvTsCX//bbeNgWnT4IYbXLp854md1H+v\nPp+t/QyAuhUvvHiSujBNGEqpwmvLFvjzz6zt8ePh7rtdvnz076PZH7+f7zZ/h4guyHm5dJSUUqrw\natECfvsNunWDxx+HIUPydPlH3T/iijJX8Pw1z+u63PnAnQsofWqMOWyM2Xie48YYM84YE2WMiTTG\nhGU71tUY80/6sZHuilEpVUhlX/yodWs7nHbUKJcvf3vZ26w9sJbSjtK8efOblPcr74YgSx53NklN\nBrpe4Hg3oEH6IwL4EMAY4w28n368CdDHGNPEjXEqpQqTN9+0a3FnrGsBcMUVLs3iBpgWOY1nFj5D\npymdOJ503E1BlkwXTRjGmMeMMRXz+sIisgS40H+tO4DPxfoLqGCMqQ60AaJEZIeInAG+Tj9XKVXc\nffwxjBwJP/0EXbtCXFyeX6J9zfY0rtKYN256g0qlK7khyJLLlT6MasBKY8wa4FPgZ8mf3qMawJ5s\n23vT9+W2/+p8eD+lVGE2bZotIJjByyur9IcLdpzYQUCpAOpVrMfqiNWUdpR2Q5CFx+nT4OdnK7wb\n4/IN2GW56B2GiLyIbTaaBAwAthtjXjfGBLs5NpcYYyKMMauMMauOHDni6XCUUpdi1iwYMAAy/hZt\n3Rp++MF+I7rgSMIROk/tTPtJ7dkdu7vYJouoKNti16aNnccINq8W1AAwl0ZJiYgYYw4CB4FUoCIw\n3RizQERcqyd8rn1AzWzbQen7HOfZf77YJgATAMLDw3XcnFJFzfz5cO+9WR3dzZrZWdwu1ogC2H58\nO4cTDtOgcoNi2Qz12Wfwv//ZaigZypa1LXYBAQVzdwGu9WE8YYxZDbwFLAOai8hgoBVw12W89w/A\n/emjpdoCsSJyAFgJNDDG1DXG+AK9089VShU3ixfbiXkpKXa7QQNYsAAqV3bp8jRnGqnOVNrXbM8f\nD/7Bj31+pKxvWffFWwBEYO1a+L//g4QEu2//fpssAgLgvvtgxgy7fHlAgD1eUAnDlTuMSkBPEdmV\nfaeIOI0xt57vImPMV8D1QBVjzF7gJezdAyLyETAXuAWIAhKBgenHUo0xw4CfAW/gUxHZlMfPpZQq\nCsqVs81OSUlQuzb8+qsdEeUCEeHxeY+zJ24PX931FSHVQtwcrPuIwIoVNhHMmAE7dtj9oaFw113Q\nv7+dknLTTVCqlOfiNMVp9mN4eLisWrXK02EopfJi/Xrbf/Hdd1C/vsuX/bX3L9pNakcp71L8PuB3\nrg4qWmOrFjEyAAAgAElEQVRj0tIgMdHmzD/+gGuuyTpWrRr06AGPPmqThjsZY1aLSLgr5+pMb6VU\nwdq82d5NlCljt0NDYc2aPLertA1qy9QeU/F3+BeZZJGSYlvhZsyw9RN794Z334V27aBVK+jQAXr1\ngvbtwdvb09GeSxOGUqrgrF9vCwc2bQpz59qeW8hTspi5ZSYbD29k1LWj6BfSz02B5r9hw+Crr+B4\nttlp69bZn97eUBQaR7T4oFKqYERGwo032m/MpUtt720erT+4nj4z+vDS4peYFzXPDUHmj8REmDkT\nXngha9/+/fajN2oEL75oO7YXLfJcjJdC+zCUUu63cSN06mQXQgKoUAEWLrTtMHngFCePz3sch5eD\n/3b5b6EqKBgfbyeoz5hhb54SE+3+HTugbl3YsMHeSTQpZIWOtA9DKVV4bNhgm6EykkVAAPzyS56S\nxdoDa9kbt5fbGt7Ge93eAygUyeLECTtqyd8fJk6Ep57KOtamjR3hlNHq1ry5Z2LMT9okpZRyn8jI\nnHcWAQHw8892JreLth7dys1Tb6bHNz1YHLMYY4xHk8WRI/DJJ3amdWCgvaMAmxw6doSxY+3y43//\nDc88A1WreizUfKd3GEop93A6oW9fOHbMbmfcWVydtxFNV5a7ksZVG1O+VHna12zvhkBdc+yYHcG0\nZIn9aGCbmKKi7PNatWzXTHGmCUMp5R5eXvDNN3D99Xap1Twmi+3HtpPiTKFJ1SbM6zsPHy8ffL1d\nL0Z4uWJi7N2DCDz9NFSqBDt32iTRpYtNHrffDlWqFFhIHqcJQymVv0Syhsk2aWI7t0+fto36Ltp2\nbBudpnQiJS2FpQOX0rBKQzcFm9P27TB9un2sWWP3Va0Kw4fbRDFjBgQH2z77kkgThlIq/yxbBi+9\nZL9Zy6evcheS95IdBptwmlRtQo2AGvkZYQ4i8M8/dqgrwMsvwxdf2Odly0L37rZvwum0CSOPg7qK\nHe30Vkrlj19/hc6d7c9u3ew40zz65+g/nEg6QYPKDfhj4B/8dN9PLhUTjI6OZsiQIQQEBODl5UVA\nQABDhgwhOjr6nHNF7CS5556Dhg2hcWM7+Rxsl0v//nYW9uHD8PXXcPfd4HDk+aMUTyJSbB6tWrUS\npZQH/PijSKlSIvb7WKRaNZGtW/P0EmsPrJWqb1WV8AnhciLphMvXzZ07V/z9/cXhcAiQ+XA4HOLv\n7y9z587NPPfPP0Xq1MkKE0QqVxb54Yc8hVqsAKvExe9YvcNQSl2e6dNtpbzkZLsdFGSHEjXMW7/D\nkYQjxCbHUql0JZc7t6Ojo+nVqxeJiYmkZJRIT5eS4iQxsQ23376L//3vEGAn0O3aZQviDhlib4YO\nHoTbbstTqCWW9mEopS7dZ5/BoEFZ40zr1rXfwnXruvwSkYciaVK1CTcH38ziBxYTVj2MUj6u1fAe\nM2bMOYkCOmOX6rkTCCQ1FcaM2cITT1SjWjVbv6lZMzuIS+WN/sqUUpfms8/gwQezkkXDhvbOIg/J\n4vut39PmkzY8POdhnOKkXc12LicLgGnTppGS4gW0zLb3XSACCAS2A//h+PFHM4+GhGiyuFR6h6GU\nujTXXQdXXmmr6rVoYWdwBwbm6SWijkeRnJaMn7cfIgIuTuBOSLCruMbHTwC6A05sgjgDjAOuAGYA\nGwBIStIMkR/cWnzQGNMV+B925byJIvLGWcf/BfRN3/QBGgNVReS4MSYGiAfSgFRxoTiWFh9UqoBt\n3gzPPw+TJ7s8OUFE7OJHNdsB8Ev0L9xc72aXy318+CGMGGEX6cuyBugF7Mz1moCAAGJjY116/ZIm\nL8UH3ZZ2jTHewPtAN6AJ0McYk6NOo4i8LSItRKQF8Bzwu4hkqxZPp/TjLn0YpZQbpaTAyJF2vGmG\nJk3sGFQXk0WaM40n5j9B+0/b89GqjwDoHNz5vMni2DH49FM7H2L1aruvXj2bLNq2hXbtZuLj0xBo\nxfmShcPhoH///q5+SnUB7mySagNEicgOAGPM18AdwObznN8H+MqN8SilLlVCgp2QMG8eLFhgF3II\nCMjzyxhjOJxwGF9vXyr6Vcz1nFOnYNo0O/dv0SK7lCnYvodWrWzh2z177GCs6OhQQkL2kpp6/vd0\nOBwMHz48z7Gqc7mzYa8GsCfb9t70fecwxvgDXbGNjhkEWGiMWW2MiXBblEqpCzt61H5Lz0tfsGjN\nGtsElQeHEw7z287f8DJeTLlzCsseXMa9ze7NPL5nj11QCCA1FR5/3FYUAbj5Zvj4Y1ueA+wkuqAg\n+zw4OJjp06fj7++P46zZdQ6HA39/f6ZPn05wcHBeP7XKjasTNvL6wDYoTsy23R8Yf55z7wXmnLWv\nRvrPQGA9cO15ro0AVgGratWqlR/zWJRSGWJiRBo2zDnT7cUXRZxOl19i+7HtUufdOlL636Vl1b5V\nmfujo0Xeekvk6qvty3bokHXN6NEin30mcuyYa+8RFRUlQ4cOlYCAAPHy8pKAgAAZOnSoREVFuRxn\nSUUeJu65s0lqH1Az23ZQ+r7c9Oas5igR2Zf+87AxZha2iWvJ2ReKyARgAthO78sPWykF2PW3u3WD\nAwfstjEwfryd8ZYHgWUCKetblqqBVbmy3JWALb8xbVrWOaVLQ/Xq9u7Cx8eWo8qL4OBgxo8fz/jx\n4/N2ocoTdzZJrQQaGGPqGmN8sUnhh7NPMsaUB64Dvs+2r4wxplzGc+xMnI1ujFUpld3y5XDNNVnJ\nwtcXvv3W5WQhIry/4n02Hd7Mzq0B3HTgZ1InLibAqzpg6zeVKwd9+tiJ4keOwHff2WShCi+3/ecR\nkVRjzDDgZ+yw2k9FZJMx5tH04x+ln9oD+EVEErJdXg2YlT5ywgf4UkTmuytWpdRZ6te3db3j423V\n2dmz7boWLnpi9mjei3wFR1x9UsZtgFR7ZzFvnl1H4rHH7HKmfn5uil+5hVvnYRQ0nYehVD7avh3u\nvRc+/9zW0riAtDR7U1KtGlx1FUydv4X7f+0E898l8HBv7rzTJorrr9fKr4VNXuZh6A2gUsrOsXj2\nWfunf0ZpjwYN7OSH88yRSE2FxYvt8NfZs+Gg71KC+o9m86jZ3HdzY9Yt3sHt4/3p2NGuJaGKPk0Y\nSpV0J0/aP/9//RXmz7eLIFVMnyNxVrLIWEwvLc2uPLd7d/oBv5OYp25jryOWd/96l1HXjWLMG/4F\n+zmU22nCUKok27HDTqPeutVub9lip1aPGJF5SlKSLRM1Ywbs2we//WbvGFq3Bt+AWO683Zs+d1Vg\nq+ND1h5Yw3PXPOehD6PcTROGUiXV8uVwxx12Yl6GV16xvdHYWdYffghz59qJ3hn27IGaNWH4W2u4\n/8e72R/UlpYtpxFm+nBf8z4F/CFUQdISjkqVRJ9/Dp06ZSWLUqVI+ORLPq89ihMnbTNUZKQd6pqQ\nAOHh8J//wLZtNlkA7Dy1mR0ndrDlyBbikuM89EFUQdI7DKVKmmnT4IEHMjeTylXlhSazGT+kPSkp\nMGUK3H+/7dZwOqFnT6hd2557OOEwby+bwtPtn6ZfSD+8jBc9G/fEz0fHx5YEmjCUKmGct92BV7Nm\nsHEjG2nKbfFziPm7Ll5e9qajalV7Xo0aWfWbAI4mHiX0o1AOnjpIFf8qDGw5kPua3+eZD6E8QhOG\nUiXArqgUZs5xMGMGNGlSjglz5iAvvcT9y96jUYMAXrjLdmdkJIvsElMSKe1Tmir+VehWvxs7Tuzg\n5uCbC/5DKI/TiXtKFWPvvw+bxv3KM9se4lZ+ZBPNCAqyw2GNsdMvLjSR7o/dfzDw+4E83e5pHgl/\nhKSUJHy9ffH20okVxUWhWEBJKVWwRGDjRnj3XfscESp+Oob3tnWmDrtYWOYOZk06zpYtWdMrLjbr\n+ttN3xJ1PIop66fgFCelHaU1WZRg2iSlVBEmYpenmDnTzpP45x+7/+YOiTQdO4j71mQVgb4iIIk7\nW++DspUu+JqLdi4i5mQMA1sO5D83/oeggCCeuPoJvIz+fVnSacJQqohxOm1ZDl9fmDo1x4AnKleG\nh2+IJvj+u2Dr+qwD7drZsrBXXnnB1569dTY9vumBn48fHWt1pEHlBjzT4Rk3fRJV1OifDEoVAWlp\ntm7TY49BrVowaZLd37WrHc00ZIit7HFo0o/855dW+GVPFo8+ai8+T7IQEVbvtwtmd6vfjdBqobxw\nzQvUrlDbvR9KFTl6h6FUIZacbJcrnT0bDh/O2r9kCQweDIGBduZ1Zsmnh2ZBbKx97utre70HDTrv\n6x9JOEKv73qxbPcy1jyyhpBqIayKWIWPl341qHPpHYZShUhyMvz4o13DGqBUKVi61CaL4GB45hn4\n+2/48susa3LUBxw/nuQmTThetizX+/jgFRFBQEAAQ4YMITo6OvO0pJQkACqVrkTCmQQqla7Evji7\nIKYmC3U+OqxWKQ9LSLBFYmfMsMkiPt6uRnfkiE0Yv/1m+yZCQnKpNL5kib3F6NsXgHnz5vFkz57E\npaZyMDU18zSHw4HD4eC7775jX7V9vPDbC0y/ZzrX1r6W7ce2U8W/ChVLVyzAT60Ki0KzHoYxpivw\nP+yKexNF5I2zjl+PXZp1Z/qumSLyiivXKlWUxcXZpGAM/OtftshfhpYt4a674MwZmzBuuCGXF3A6\n4c03YdQou65pkyZEBwTQq1cvEk+fPuf0lJQUUlJS6HV3L8L+G8aRxCN8ueFLrq19LQ0qN3DfB1XF\nitsShjHGG3gfuBnYC6w0xvwgIpvPOnWpiNx6idcqVWQcPw4//GDvJH75Bf74w5YI79HDDo3t1cvW\nbapX7yIvdOgQ9O8PCxbY7bQ0GDKEMS1akJKScu751YCbgDWQGpVKrc21eOzhx7in6T35/AlVcefO\nO4w2QJSI7AAwxnwN3AG48qV/OdcqVahERdlRTIsW2eGwYO8sVq60CePmm+3DJQsX2mRx8GDWvg4d\n4OuvmdakSe4Joz3QAPCHlC0p/DT5J77835fnnqfURbiz07sGsCfb9t70fWdrb4yJNMbMM8Y0zeO1\nGGMijDGrjDGrjhw5kh9xK3VZ9u6FceNsaXCw9ZkWL7aT7G66yTY/7d9vk4jLzpyxS6h27pyVLIyB\n55+3Lx4UxKlTp+z+8sCtQFj6tYuBv4Av7GbmeUrlkaeHQ6wBaonIKWPMLcBs7N9CLhORCcAEsJ3e\n+R+iUhe3c6dtapo+3Y5iAjtX7u67oXx525ndqpXtvL4kixbBW29lbQcG2ll7nTtn7ipbtizx8fH2\n/jwciAXWASeA+eQ4T6lL4c47jH1AzWzbQen7MolInIicSn8+F3AYY6q4cq1SnnbgQNbze+6xndd/\n/w2lS9t+icceyzreufNlJAuALl0gIiLreWRkZrLYfmw7g34YRKNHGuFwOGA5NlFMBZw5X8bhcNC/\nf//LCESVZO68w1gJNDDG1MV+2fcGchTPN8ZcARwSETHGtMEmsGPAyYtdq1RBE4ENG+ydxIwZEB1t\nh76WLWsXHKpf345u6tYNypS5zDc7dsxO5/7Xv7LG0o4da5e+e+gh8PIiJS0Fh7eD7//5nklrJ1Gh\nUgV8/HxIiU+x9+q5cDgcDM++yIVSeSEibnsAtwDbgGjghfR9jwKPpj8fBmwC1mNbWdtf6NqLPVq1\naiVKucOPP4rUry9i04Z9VKgg8vffbnqzK66wb/Lhh+ccXrprqVw/+XqJ+CFCRETik+Nl6E9DZdvR\nbTJ37lzx9/cXh8MhQObD4XCIv7+/zJ071w0Bq6IMWCWufqe7emJReGjCUPkhLU1k6VKRJ58U+esv\nu++PP+y/lqpVRR5+WGT+fJHk5Hx+47g4++LZs5K/v8ihQxJ3Ok52n9wtIiKfr/tcGI0Evh0oSSlJ\n57xMVFSUDB06VAICAsTLy0sCAgJk6NChEhUVlc8Bq+IgLwlDZ3orhZ3K8Pvvtqlp5sysgUiPPWZH\nPDmddt5Ehw7g7Y7lIH77DR58EHbtytp3xRUwaRITqu3l6V+e5ubgm5lxzwySU5P5aNVHDGgxgPJ+\n5d0QjCpJCs1Mb6UKszNn7BDYevVsDafbboPERHusTh3bH9Gnj9328oJrr3VDEKdOwciRtkhgukQH\nfPdAa4KGPseNLW6hxrafiD8Tz4mkE6Q6UynlU4on2j7hhmCUujBNGKpESUqCn3+2dxJz5kDdurB2\nLfj72+qvvr52xnXLlrnUbXKHhAT46isESPMCn/IVeWJUKBPjFnND5HhubNGDrvW7snHwRpoGNr3o\nyynlTpowVInx6qu2/FJCQta+tLSsYn/vvFNAgYhkZaNq1fjgldv439YpPJnQnMGv/cz9Z6LYuPAZ\n+jbvi4jg7eWtyUIVClreXBVLJ0/aeW09e9oaTmAn0CUk2Al0//mPXc40MtImiwIhAtOns791I8Yt\nfI29cXsB+KdeANuqwE831YLq1bmm9jX8+dCfPNjyQUyB3OYo5Rq9w1DFxsmTWXMkFi6EjLJKt98O\nAwZAv372eZ06BR/bvq0rqfHsv5EffuC6xyBq2Yskl/blXx3+xZDWQ+lavxs3B7taUEopz9CEoYq0\nAwdsh3WdOrY8R8bicl5e0KmT7bju2tXuq1TJPgpS7Klj3DC2BWuce9myHBoB922A9bVLEVq6DgAN\nqzSkYZWGBRuYUpdAE4YqcnbvzrqTWL4cBg60k6JbtIAHHrBDX++80xb9K2g7TuzgzT/eZMvRLfze\n6E3KDx5MwjV7KRMAm6tCo6PwcsNH4I03oEKFgg9QqcugCUMVKV262LUkMpQqZedIgO1Hnjy5YOPZ\ncmQLM7bMoJxvucyhrhPWTABg6zPtaXwUvt8LtWKhdMOmsPQj6NixYINUKp9op7cqlERg0yZ45RV7\nt5Axv7RaNTsEtlcv+OorW8vps88u/FrR0dEMGTKEgIAAvLy8cl3j2lVrD6zl7WVvs2z3MgB+2/kb\noxaNYtyKcQDUq1iPd7u8y+qHV9GoUQcAGiaWpvS/37CrJGmyUEWZq1PCi8JDS4MUfVu3irzwgkjD\nhjkrZERG2uMHDogkJLj+epdTWyklLUV+jvpZXlr0kpxMOikiIt2/6C6MRh6b+5iIiGw/tl0G/zhY\npn/zkqQ9NzLnC6xfL9Kjh8jOnXn5FShVoMhDaRBtklIe5XTCihXQoIEt/710Kbz2mj1WqZK9u7jr\nLrjqKrvviitcf+3o6Gi7xnXG9O1sMte47tWLyMhIgoOD2Re3j+//+Z6jiUf5v+v+D4A7v76TpNQk\n2ga1pWv9rvRq0ovqZavTtb7tSa9/HD6YdBBmpS/K3aUrXHedfR4SYuuMKFVMaMJQBS4tzdZlmjnT\nPvbutZUxhgyBO+6A1attk9N114HPZfwfOmbMmNyXLM1wFSQ1SeKhDx9i8TuL+efYPwydOxRfb19G\ndhyJr7cvA1oMwM/Hj6CAIAAGtBjAgBYD4MQJeOopGD8+a/wuwAsv2A+nVDGkCUMVqKNHoWlTOHw4\na1/NmnYYLNiRTR9+mD/vNfXrqaQEpNgVVgDuBaoD07GL/tYGaSEs22H7I1pVb0W/kH60vrI1qc5U\nfL19+aD7BzlfNDnZZrfXXsuaEZihXz87lVypYkoThnKb5GRYsMAOfy1dGj74AKpUsUmhbFnb1NSr\nF7Ruffl1m9YeWMtfe/+iXsV6dKnfhV93/Mqpx09BMvBG+kmVgQrAFdiEsQWIg7R9aQCU9yvP1B5T\nL/xGjz0Gn3ySc1+HDvDf/0KbNpf3IZQq5DRhqHz388/w+ed2Heu4OLuvbFm7YFypUnZ56ipVXE8S\nSSlJRJ+I5uTpk3Ss1RGnOLnz6zuJOh7FFz2/oGX1lkxcM5EPVn3Afc3vo0v9LtSrWM8uTxoH+AGn\ngR/Sf2bcGOy1j3IBF6gNkjE8KyPYJ5+0kz6cTlvm9s03bebTEh6qBHDrsFpjTFdjzD/GmChjzMhc\njvc1xkQaYzYYY5YbY0KzHYtJ37/OGKOLXBRicXEwfXrWfIjZs+HLL+3+0FBb9G/FCpsswN5hZHy/\nigj74/ezYt8KklOTAfhg5Qf0/KYnU9ZNAWB+1Hyaf9icu7+7GwAv48W6g+vYcnQL245tA6BT3U48\n2OJBugbbzug6FeoQcTQCxycOmyTAJoij5Fjn+rxrXIvY+iLt29sPlKFJE7ts6rhxsGWLvUXSZKFK\nCleHU+X1AXhjl1etB/hil2FtctY57YGK6c+7AX9nOxYDVMnLe+qw2oJz/LjI5Mkit94q4utrh75m\nrE73998ib74pEhUlEnMiRpbELJE9sXtERGRB9AK5+9u75fG5j4uISOzpWGE0wmhk8+HNIiJy/6z7\nhdHII3MeERGR9QfXy1XvXSVdp3WV1LRUERFZvHOxrDuwThLOnH+MbVRUlPj7++cYTnv2w9/f/9yV\n6BYvFrn22qwxvU2aiKSm5uevT6lCg0IyrLYNECUiOwCMMV8DdwCbsyWr5dnO/wsIcmM8Kp/89pud\ncZ0asB2qbYDqVbim1rXsitvB/00bzIH4A6x9ei3eXt6ET7iL1QdW81639xjWZhj74vbx3ebvaFjZ\n1k4KKBVAvYr1qOBXgeQ0e4cRERZB9wbdaR7YHICQaiH8M+yfHDFcV+e6i8YZHBzM9OnT6dWrV+Yw\n2gwOhwOHw8H06dMJDg62qeHXX+3t0JIlOV8oKsoO3dI+ClXCuTNh1AD2ZNveC1x9gfMfAuZl2xZg\noTEmDfhYRCbkdpExJgKIAKhVq9ZlBVwSREdHM2bMGKZNm8apU6coW7Ys/fr1Y8SIEdStV5eUtBRK\n+ZRid+xu5m2fx+HjZ6i47TFmzICYG9uTUCqKyd2/w9f3Oq7s8Qm7a77NLXV78tP917In1sG979q6\nHYcTDlO9XHXCqofh6+1LRb+KgP2i/6LnF9QuXzsrpsdzzrjuUKtDvn3ebt26ERkZydixY5k6dWrm\nZ+7fvz/Dhw+3yWLLFnjoIfjzz5wX+/jY/c8/D/r/llJubZLqBUzMtt0fGH+eczthx6xUzravRvrP\nQGxz1rUXe09tkjo/p9MpM+fMFH9/f/Ep7SO0QbgZwc/Oeva+y1t8XvaRUb+NEqdT5OE359mmomcr\nZLbM+D0TLIxGvoj8QuLjRb7a8JXc/tXt8tYfb4mInRn907afZO2BtZKcmuzhT5wHhw+LlC6d1QTl\n4yPy0EM6Q1uVCBSSJql9QM1s20Hp+3IwxoQAE4FuIpIxYh4R2Zf+87AxZha2iWvJ2derc/247Uc2\nHd5E5+DOmSOIHp/7OMkxyTgTnfa+8pb0kzdAysEUSC4PEsvOgzsxBv766Sqo8BDeSVdy651Oet3l\nRaMOcwmqGkBV/6p4e0HvZr3p3ax35vv6ePlwS4Nbco2p0IiPt6OcypSBhx+2+6pWtXXRP/4YHnzQ\nrrFdu/aFX0epEsidCWMl0MAYUxebKHoD92U/wRhTC5gJ9BeRbdn2lwG8RCQ+/Xln4BU3xlpknDx9\nkq1Ht+Lj5UP4leFEHY+i9/TexJyMYf+I/fh6+/L60tf5c++fOLwdtKzeknK+5UhKS4L0UUqkAsuB\npEBI7AsMhIU14WcnpQe8Bn3gtafrcfr0RLp1s0Niras88ZHzx65ddsLdhAkQG2trjNx/f9bQrRde\ngGefhRo1PBunUoWZq7cil/LA/h27DTta6oX0fY8Cj6Y/nwicANalP1al76+HbYZaD2zKuPZij+LY\nJPX+ivfl4R8eljX714iIyHMLnxNGI92/6C4iIkcSjmSOMtp2dJuIiIz9c6wMnz9cFu9cLCIiCWcS\npGzlsukjg0z6z+dzFPeDEwKTpWzZhp75oO7gdIr8/rtIr14iXl5y1ge2w7yUKuEoJE1SiMhcYO5Z\n+z7K9nwQMCiX63YAoWfvL46SUpKIS46jWtlqbDq8iSFzh7A7djc7Ht+BMYYPV33IxsMbaVW9FS2r\ntyS0Wihh1cMyRxlVLl2Z5Q8uJ7hSMFX97YpBT7Z9MvP1nU5Yt9KfU8deBnoCA4HFwCLgCDAbmAH8\nBqSQmFhMKt7v2GErF27YcO6xBg1gxAi4556Cj0upIkxneheg06mnWXdwHQ0qNaCyf2VGLx7Nv5f8\nm3ub3csXPb+gXKlyLNllu2n2xO2hVvlaPHH1EySlJHF9nesBuLfZvdzb7N7M1zTG0K5mu3Pe6+hR\nGD0aZs2C/fsBnko/0g2bMP7CFlZKy3Fd2az2p6InOTmriSkoKGfBKoCbboInnoBbbskqXqWUcpn+\nq3ETEWHniZ3M3po1S7jx+41pN6kd86PmA1C9bHUAEs4kAFAzoCY/9/uZfU/to2aAHS8wKGwQj139\n2EXXfD5zBubPt+U4wPbpTp5sk0WtWhAS8ive3tcCGRPuhbOTxXlnPRdmx4/birFhYTB0aNZ+X1+I\niLC/iEcegchIW9jq1ls1WSh1iYxtwioewsPDZdUqz1QRcYqTTYc3EZccR4daHVh3cB0tP24JwNF/\nHaWyf2Xu+vYuth3bxvMdn6dP8z4knEnAy3hR2lH6kt4zKckuVzpzJvzwA5w8aZdgWL/eHv/yS7uO\nRKtWsGNHNCEhIbmuDZHB398/c22IQi0jO06daj/4mTN2v78/HDgAAQF2++RJW7ajfHnPxapUIWeM\nWS0i4a6cq01Sl0hE2H58O2UcZagRUIO3l73NyF9HcnWNq/lr0F80D2xOvYr1aFK1CSdPn6Syf2W+\nu/s7vEzWX7dlfMvk+X3PnLF/PAP07Gm/NzM0awY9etj1Jry94b5sY9LyNOu5sIqKshUMv/3Wtrmd\nLWM1pptustsVKhRsfEoVcyX63jyvaz3Hno7FKbZyXY9vetBwfEMmrpkI2NnJQQFBNKnaBBHB28ub\n6MejmdNnDsGV7Jdw9mSRF7Gx8MUXNkFUqQLH0merdO9uW2Jefx3++cf2744ebZNFbjJmPUdEROT4\nzBEREURGRtKtW7dLis9tnE5ITc3aPnnS1kg/O1m0bm0X0ThwICtZKKXyn6vDqYrCIy/DavOy1vPp\nlFqfuCIAAArYSURBVNPSaXIn8XnFR1buWykiIi/8+oJUfrOyjF40WkTsTGqn0+ny+7ti1SqRW27J\nKu6X8Zg9W9LfM1/frnA4c0bk119FHntMJChI5Isvso45nSL169tfQlCQyMiRIps2eS5WpYoBCsuw\n2sLqoms9l0rh9nG30zKmJX89+helfEoRmxyLiLDh0AbCrwznuY7P8UqnVzLvGkw+lLg+eNCOamrZ\nEtq2tXcKc+faPtrrrrPLLvTsmTW3rNhU1T5+3Lat/fST/cAnT2Ydmz49q23NGBgzxvZRXHutdl4r\nVcBKZMLIba3n62vAhgA4tgUwkNo2lZWHV7J6/2pa12jN53d+To2AGlTws+3il9L/kJvdu22n9YwZ\nsGyZvYcYONAmjNBQuxBRly4QGJgvb1f4DBtmm5OcztyPr1xpm6UyFve+/faCi00plUOJTBjTpk3L\nkTDKtYDFd0LgKdi0FRbHw8e/wNETfrQcZUc6NQ1smm/vHxdn/0hOS7N3ExlLQ/v6QufOkNGVYAwU\ntVGuuUpLg40bYfFiiImxHdcZqlU7N1kEBdlJd3fcYW+tfErk/6ZKFTol8l/iqVOncmzfuB3WnIQe\nWyHIF4Ykw5DlAKehcVO7ZvMrr9gvsku0ebO9i5gxAxISYNs22+TUuzccOmSbm7p3zxoRWqSdOgWr\nVtly4X/8YW+dYmPtMWNg1CioVMlud+4ML70EV19tJ9R1726zaLFpb1Oq+CiR8zACAgKIj4/P3O4C\nPAlcB5x3RsSxY1lfcqtX22/+Vq3sMKU6dc77BffFF/Daa3bJhQzlyv1/e/caY0V9xnH8+3MLBRZc\nDRq5CixeKmBDE6tSiikGLQiBmvDCGqolJqSJRokvtL5rkyZUTWubbNPWUGqatpKm0IitSACpjSmt\nq1svXVgbKF4WSbABuhju8PTFf+g5rKwMC7PDnvP7JBPOzJnZ80w27HPm+d9SAjmH/HPhOHgwPQEM\nGJD2N2xINbSeSkyQanB33pleHz8Oe/em7l9m1uc8DuMMFi1axPLly/9fllqXbZ8FpgFfAWZKTJMY\ncOIETJ5cSRYAa9fCsmWV/aYmuP56Ysr1vDt0Ci92TmHBD25h1Kg0W8XWrenyBQvSk8SsWZUZLPqN\no0dhxw5ob0/Zrr09jRDs6EhJYubMdN7kyadPFiNGpIbqmTNPXbmuocHJwqyfqMsnjO3b8416fru1\nleY9e1KJZfbsypvz58Pzz/d4bQfXsrGlg/vvT1+eO598lklsoWHi+LTOwrhxqavTkCFnc3vFikjj\nGzo7U7vCqFHp+MGDMHVqmsyvekxEtaeegqWVCQ9pbk5TckyblrYZM2DiRJeZzC5AfsI4g7yjnpsn\nTTrt9cfvW8LhcdcxpKON46+10bBvzynvH2n+HNOzVUYvvRQufef3qQzT3SWXpMQxZw48+WTl+Asv\npJbwpqZUvxo2LCWXQYPSNnRoOnbSgQOptHPsWHoSOHIEDh1Kxw8cSF2smpsr5y9blhqfP/oo9eXd\ntStth9Oa2jz+ODzySHo9eHDKej0lC+nk7IYVHR2V4ehmVjPqMmFAzrWeqxw+nCovq1fDc8/NY9as\neaxcDw0RLL59JzOa3mLWFW8zdv8WPj/tZphadfG2bacPYt++ygRQ1Z54Al5+uefgFy+GFSsq+zNm\nQFtbz+cvXXpqz6Rnnkmt7j3ZsePU/WuuScll9Gi47rpUdpo0KcU9ZUr1CkuJk4VZTSo0YUiaDfwY\naCCt7/39bu8re/8O4ADwzYhoy3Pt+TBx4kRaWlpoaWn51PMefjit6tnVVTm2fXuq4kjil+vHkFag\n7WF50kcfTXX/995L2/vvp2/lJ59sug+y2Lv30wPv3s30TKWekz2UTrrsstMnjKam1BI/fPipx1eu\nTI9Kjedn7ImZ9U+FJQxJDcBPgNuATqBV0pqI2FJ12hzg6my7CfgpcFPOawuxf38acLxxY1ri+aKL\nUnWnqyt9oV64MDVc91CtOr277/7ksRMnUpvBhx9+si/t/PnpA7q6UvvJ/v2pLeHk1n321SFD0h/z\nhob07X7gwNSq3tiY3rvyylPPf/BBWLQoJY4RIypbdZmrWk105zKzc1VYo7ekacB3IuKr2f5jABGx\nrOqcnwN/johns/13SJ2Uxp/p2tPp7fTm+/alWbJXrYJ16yql/M2b04jrHTtSE8FVV531jzYzu6Bd\nKI3eo4EPqvY7SU8RZzpndM5rz5u1a+Hee9NrKY3TW7iw0k48YUJRn2xm1n/0+0ZvSUuAJQBXdi+9\n5DR3bhpwvGBBGk82cuT5jNDMrDYUmTB2AmOr9sdkx/KcMyDHtQBExNPA05BKUr0J9OKLUynKzMx6\nVuT80K3A1ZImSBoI3AWs6XbOGuAeJTcD/42IXTmvNTOzPlTYE0ZEHJP0AGnWjQZgRUS0S/pW9v7P\ngBdIfVG3kbrVLv60a4uK1czMzqwupwYxM7PkbHpJeckyMzPLxQnDzMxyccIwM7NcnDDMzCwXJwwz\nM8ulpnpJSfoIeK+Xl18G/Oc8htMf+J5rX73dL/iez9a4iLg8z4k1lTDOhaTX8nYtqxW+59pXb/cL\nvuciuSRlZma5OGGYmVkuThgVT5cdQAl8z7Wv3u4XfM+FcRuGmZnl4icMMzPLpe4ThqTZkt6RtE3S\nt8uOpy9IWiFpt6R/lh1LX5A0VtImSVsktUt6qOyYiiZpkKRXJb2Z3fN3y46pr0hqkPQPSX8sO5a+\nIOldSW9LekNSobOv1nVJSlID8C/gNtIysK3A1yNiS6mBFUzSLcDHwK8iYkrZ8RRN0khgZES0SRoG\nvA58rZZ/z5IENEbEx5IGAK8AD0XE30oOrXCSHgZuAC6OiHllx1M0Se8CN0RE4WNP6v0J40ZgW0T8\nOyKOACuBBSXHVLiI+Auwp+w4+kpE7IqItuz1fmArad34mhXJx9nugGyr+W+HksYAc4HlZcdSi+o9\nYYwGPqja76TG/5DUO0njgS8Afy83kuJlpZk3gN3A+oio+XsGfgQ8ApwoO5A+FMAGSa9LWlLkB9V7\nwrA6ImkosApYGhFdZcdTtIg4HhFTgTHAjZJquvwoaR6wOyJeLzuWPvbl7Pc8B7g/KzkXot4Txk5g\nbNX+mOyY1Zisjr8K+E1ErC47nr4UEfuATcDssmMp2HRgflbTXwncKunX5YZUvIjYmf27G/gDqdRe\niHpPGK3A1ZImSBoI3AWsKTkmO8+yBuBfAFsj4odlx9MXJF0u6ZLs9WBSx46OcqMqVkQ8FhFjImI8\n6f/ySxGxqOSwCiWpMevIgaRG4HagsN6PdZ0wIuIY8ACwjtQQ+ruIaC83quJJehbYDFwrqVPSfWXH\nVLDpwDdI3zjfyLY7yg6qYCOBTZLeIn0xWh8RddHNtM5cAbwi6U3gVeBPEfFiUR9W191qzcwsv7p+\nwjAzs/ycMMzMLBcnDDMzy8UJw8zMcnHCMDOzXJwwzMwsFycMMzPLxQnDrCCSvijprWxtisZsXYqa\nns/JapsH7pkVSNL3gEHAYKAzIpaVHJJZrzlhmBUom6OsFTgEfCkijpccklmvuSRlVqzhwFBgGOlJ\nw6zf8hOGWYEkrSFNtT2BtEzsAyWHZNZrnyk7ALNaJeke4GhE/DZbP/6vkm6NiJfKjs2sN/yEYWZm\nubgNw8zMcnHCMDOzXJwwzMwsFycMMzPLxQnDzMxyccIwM7NcnDDMzCwXJwwzM8vlf0Y5SBFT0GmX\nAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f66019550>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "xm = np.array([0,1,2,3,4,5])\n",
    "ym = np.array([0.1,0.2,0.3,0.5,0.8,2.0])\n",
    "\n",
    "#### Solution\n",
    "m = GEKKO()\n",
    "m.options.IMODE=2\n",
    "# coefficients\n",
    "c = [m.FV(value=0) for i in range(4)]\n",
    "x = m.Param(value=xm)\n",
    "y = m.CV(value=ym)\n",
    "y.FSTATUS = 1\n",
    "# polynomial model\n",
    "m.Equation(y==c[0]+c[1]*x+c[2]*x**2+c[3]*x**3)\n",
    "\n",
    "# linear regression\n",
    "c[0].STATUS=1\n",
    "c[1].STATUS=1\n",
    "m.solve(disp=False)\n",
    "p1 = [c[1].value[0],c[0].value[0]]\n",
    "\n",
    "# quadratic\n",
    "c[2].STATUS=1\n",
    "m.solve(disp=False)\n",
    "p2 = [c[2].value[0],c[1].value[0],c[0].value[0]]\n",
    "\n",
    "# cubic\n",
    "c[3].STATUS=1\n",
    "m.solve(disp=False)\n",
    "p3 = [c[3].value[0],c[2].value[0],c[1].value[0],c[0].value[0]]\n",
    "\n",
    "# plot fit\n",
    "plt.plot(xm,ym,'ko',markersize=10)\n",
    "xp = np.linspace(0,5,100)\n",
    "plt.plot(xp,np.polyval(p1,xp),'b--',linewidth=2)\n",
    "plt.plot(xp,np.polyval(p2,xp),'r--',linewidth=3)\n",
    "plt.plot(xp,np.polyval(p3,xp),'g:',linewidth=2)\n",
    "plt.legend(['Data','Linear','Quadratic','Cubic'],loc='best')\n",
    "plt.xlabel('x')\n",
    "plt.ylabel('y')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6: Nonlinear Regression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Optimized, a = 0.5990964\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x15f65fbfa90>]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nv81+9zgAs8AAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f6559d940>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "# measurements\n",
    "xm = np.array([0,1,2,3,4,5])\n",
    "ym = np.array([0.1,0.2,0.3,0.5,0.8,2.0])\n",
    "\n",
    "# GEKKO model\n",
    "m = GEKKO()\n",
    "\n",
    "# parameters\n",
    "x = m.Param(value=xm)\n",
    "a = m.FV()\n",
    "a.STATUS=1\n",
    "\n",
    "# variables\n",
    "y = m.CV(value=ym)\n",
    "y.FSTATUS=1\n",
    "\n",
    "# regression equation\n",
    "m.Equation(y==0.1*m.exp(a*x))\n",
    "\n",
    "# regression mode\n",
    "m.options.IMODE = 2\n",
    "\n",
    "# optimize\n",
    "m.solve(disp=False)\n",
    "\n",
    "# print parameters\n",
    "print('Optimized, a = ' + str(a.value[0]))\n",
    "\n",
    "plt.plot(xm,ym,'bo')\n",
    "plt.plot(xm,y.value,'r-')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7: Machine Learning\n",
    "\n",
    "Approximate $y = sin(x)$ with an Artificial Neural Network\n",
    "\n",
    "__Trigonometric Function (trig=True)__\n",
    "\n",
    "* Input: $x$\n",
    "* Layer 1: linear layer, 1 node, $l1 = w1 \\; x$\n",
    "* Layer 2: nonlinear layer, 1 node, cosine function, $l2 = \\cos(w2a+w2b\\;l1)$\n",
    "* Layer 3: linear layer, 1 node, $l3 = w3 \\; l2$\n",
    "* Output: $y = \\sum{l3}$\n",
    "\n",
    "__Artificial Neural Network Description (trig=False)__\n",
    "\n",
    "* Input: $x$\n",
    "* Layer 1: linear layer, 2 nodes, $l1 = w1 \\; x$\n",
    "* Layer 2: nonlinear layer, 2 nodes, hyperbolic tangent activation function, $l2 = \\tanh(w2a+w2b\\;l1)$\n",
    "* Layer 3: linear layer, 2 nodes, $l3 = w3 \\; l2$\n",
    "* Output: $y = \\sum{l3}$\n",
    "\n",
    "See [Online Neural Network Demo](https://playground.tensorflow.org) with TensorFlow."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "w1[0]: 0.821782978\n",
      "w1[1]: 0.728869969\n",
      "w2a[0]: -1.41731735\n",
      "w2b[0]: 0.548984509\n",
      "w2a[1]: -0.131957576\n",
      "w2b[1]: 0.592683118\n",
      "w2a[2]: -0.330742133\n",
      "w2b[2]: 0.144440713\n",
      "w2a[3]: -2.92831117\n",
      "w2b[3]: 0.66823565\n",
      "w3[0]: -1.5171649\n",
      "w3[1]: -1.5171649\n",
      "w3[2]: 1.62870093\n",
      "w3[3]: 1.62870093\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x15f661ca240>]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f661b25f8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "from gekko import GEKKO\n",
    "\n",
    "# generate training data\n",
    "x = np.linspace(0.0,2*np.pi,20)\n",
    "y = np.sin(x)\n",
    "\n",
    "# option for fitting function\n",
    "select = False # True / False\n",
    "if select:\n",
    "    # Size with cosine function\n",
    "    nin = 1  # inputs\n",
    "    n1 = 1   # hidden layer 1 (linear)\n",
    "    n2 = 1   # hidden layer 2 (nonlinear)\n",
    "    n3 = 1   # hidden layer 3 (linear)\n",
    "    nout = 1 # outputs\n",
    "else:\n",
    "    # Size with hyperbolic tangent function\n",
    "    nin = 1  # inputs\n",
    "    n1 = 2   # hidden layer 1 (linear)\n",
    "    n2 = 2   # hidden layer 2 (nonlinear)\n",
    "    n3 = 2   # hidden layer 3 (linear)\n",
    "    nout = 1 # outputs\n",
    "\n",
    "# Initialize gekko\n",
    "train = GEKKO() \n",
    "test = GEKKO()\n",
    "\n",
    "model = [train,test]\n",
    "\n",
    "for m in model:\n",
    "    # input(s)\n",
    "    m.inpt = m.Param()\n",
    "\n",
    "    # layer 1\n",
    "    m.w1 = m.Array(m.FV, (nin,n1))\n",
    "    m.l1 = [m.Intermediate(m.w1[0,i]*m.inpt) for i in range(n1)]\n",
    "\n",
    "    # layer 2\n",
    "    m.w2a = m.Array(m.FV, (n1,n2))\n",
    "    m.w2b = m.Array(m.FV, (n1,n2))\n",
    "    if select:\n",
    "        m.l2 = [m.Intermediate(sum([m.cos(m.w2a[j,i]+m.w2b[j,i]*m.l1[j]) \\\n",
    "                                for j in range(n1)])) for i in range(n2)]\n",
    "    else:\n",
    "        m.l2 = [m.Intermediate(sum([m.tanh(m.w2a[j,i]+m.w2b[j,i]*m.l1[j]) \\\n",
    "                                for j in range(n1)])) for i in range(n2)]\n",
    "        \n",
    "    # layer 3\n",
    "    m.w3 = m.Array(m.FV, (n2,n3))\n",
    "    m.l3 = [m.Intermediate(sum([m.w3[j,i]*m.l2[j] \\\n",
    "            for j in range(n2)])) for i in range(n3)]\n",
    "\n",
    "    # output(s)\n",
    "    m.outpt = m.CV()\n",
    "    m.Equation(m.outpt==sum([m.l3[i] for i in range(n3)]))\n",
    "\n",
    "    # flatten matrices\n",
    "    m.w1 = m.w1.flatten()\n",
    "    m.w2a = m.w2a.flatten()\n",
    "    m.w2b = m.w2b.flatten()\n",
    "    m.w3 = m.w3.flatten()\n",
    "    \n",
    "# Fit parameter weights\n",
    "m = train\n",
    "m.inpt.value=x\n",
    "m.outpt.value=y\n",
    "m.outpt.FSTATUS = 1\n",
    "for i in range(len(m.w1)):\n",
    "    m.w1[i].FSTATUS=1\n",
    "    m.w1[i].STATUS=1\n",
    "    m.w1[i].MEAS=1.0\n",
    "for i in range(len(m.w2a)):\n",
    "    m.w2a[i].STATUS=1\n",
    "    m.w2b[i].STATUS=1\n",
    "    m.w2a[i].FSTATUS=1\n",
    "    m.w2b[i].FSTATUS=1\n",
    "    m.w2a[i].MEAS=1.0\n",
    "    m.w2b[i].MEAS=0.5\n",
    "for i in range(len(m.w3)):\n",
    "    m.w3[i].FSTATUS=1\n",
    "    m.w3[i].STATUS=1\n",
    "    m.w3[i].MEAS=1.0\n",
    "m.options.IMODE = 2\n",
    "m.options.SOLVER = 3\n",
    "m.options.EV_TYPE = 2\n",
    "m.solve(disp=False)\n",
    "\n",
    "# Test sample points\n",
    "m = test\n",
    "for i in range(len(m.w1)):\n",
    "    m.w1[i].MEAS=train.w1[i].NEWVAL\n",
    "    m.w1[i].FSTATUS = 1\n",
    "    print('w1['+str(i)+']: '+str(m.w1[i].MEAS))\n",
    "for i in range(len(m.w2a)):\n",
    "    m.w2a[i].MEAS=train.w2a[i].NEWVAL\n",
    "    m.w2b[i].MEAS=train.w2b[i].NEWVAL\n",
    "    m.w2a[i].FSTATUS = 1\n",
    "    m.w2b[i].FSTATUS = 1\n",
    "    print('w2a['+str(i)+']: '+str(m.w2a[i].MEAS))\n",
    "    print('w2b['+str(i)+']: '+str(m.w2b[i].MEAS))\n",
    "for i in range(len(m.w3)):\n",
    "    m.w3[i].MEAS=train.w3[i].NEWVAL\n",
    "    m.w3[i].FSTATUS = 1\n",
    "    print('w3['+str(i)+']: '+str(m.w3[i].MEAS))\n",
    "m.inpt.value=np.linspace(-2*np.pi,4*np.pi,100)\n",
    "m.options.IMODE = 2\n",
    "m.options.SOLVER = 3\n",
    "m.solve(disp=False)\n",
    "\n",
    "plt.figure()\n",
    "plt.plot(x,y,'bo')\n",
    "plt.plot(test.inpt.value,test.outpt.value,'r-')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8: Solve Differential Equation(s)\n",
    "\n",
    "Solve the following differential equation with initial condition $y(0) = 5$:\n",
    "\n",
    "$ k \\, \\frac{dy}{dt} = -t \\, y$\n",
    "\n",
    "where $k=10$. The solution of $y(t)$ should be reported from an initial time $0$ to final time $20$. Create of plot of the result for $y(t)$ versus $t$. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x15f66195cc0>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f657da0b8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "m = GEKKO() # Initialize gekko\n",
    "a = 0.4\n",
    "m.time=np.linspace(0,20)\n",
    "y = m.Var(value=5.0)\n",
    "m.Equation(y.dt()==-a*y)\n",
    "m.options.IMODE=4\n",
    "m.options.NODES=3\n",
    "m.solve(disp=False)\n",
    "\n",
    "plt.plot(m.time,y.value)\n",
    "plt.xlabel('time')\n",
    "plt.ylabel('y')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 9: Nonlinear Programming Optimization\n",
    "\n",
    "Solve the following nonlinear optimization problem:\n",
    "\n",
    "$\\min x_1 x_4 \\left(x_1 + x_2 + x_3\\right) + x_3$\n",
    "\n",
    "$\\mathrm{s.t.} \\quad x_1 x_2 x_3 x_4 \\ge 25$\n",
    "\n",
    "$x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40$\n",
    "\n",
    "$1\\le x_1, x_2, x_3, x_4 \\le 5$\n",
    "\n",
    "with initial conditions:\n",
    "\n",
    "$x_0 = (1,5,5,1)$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Results\n",
      "x1: [1.0]\n",
      "x2: [4.743]\n",
      "x3: [3.82115]\n",
      "x4: [1.379408]\n",
      "Objective: 17.0140171\n"
     ]
    }
   ],
   "source": [
    "m = GEKKO() # Initialize gekko\n",
    "# Use IPOPT solver (default)\n",
    "m.options.SOLVER = 3\n",
    "# Change to parallel linear solver\n",
    "m.solver_options = ['linear_solver ma97']\n",
    "# Initialize variables\n",
    "x1 = m.Var(value=1,lb=1,ub=5)\n",
    "x2 = m.Var(value=5,lb=1,ub=5)\n",
    "x3 = m.Var(value=5,lb=1,ub=5)\n",
    "x4 = m.Var(value=1,lb=1,ub=5)\n",
    "# Equations\n",
    "m.Equation(x1*x2*x3*x4>=25)\n",
    "m.Equation(x1**2+x2**2+x3**2+x4**2==40)\n",
    "m.Obj(x1*x4*(x1+x2+x3)+x3) # Objective\n",
    "m.options.IMODE = 3 # Steady state optimization\n",
    "m.solve(disp=False) # Solve\n",
    "print('Results')\n",
    "print('x1: ' + str(x1.value))\n",
    "print('x2: ' + str(x2.value))\n",
    "print('x3: ' + str(x3.value))\n",
    "print('x4: ' + str(x4.value))\n",
    "print('Objective: ' + str(m.options.objfcnval))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 10: Mixed Integer Nonlinear Programming"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Results\n",
      "x1: [1.358909]\n",
      "x2: [4.599279]\n",
      "x3: [4.0]\n",
      "x4: [1.0]\n",
      "Objective: 17.5322673\n"
     ]
    }
   ],
   "source": [
    "m = GEKKO() # Initialize gekko\n",
    "m.options.SOLVER=1  # APOPT is an MINLP solver\n",
    "\n",
    "# optional solver settings with APOPT\n",
    "m.solver_options = ['minlp_maximum_iterations 500', \\\n",
    "                    # minlp iterations with integer solution\n",
    "                    'minlp_max_iter_with_int_sol 10', \\\n",
    "                    # treat minlp as nlp\n",
    "                    'minlp_as_nlp 0', \\\n",
    "                    # nlp sub-problem max iterations\n",
    "                    'nlp_maximum_iterations 50', \\\n",
    "                    # 1 = depth first, 2 = breadth first\n",
    "                    'minlp_branch_method 1', \\\n",
    "                    # maximum deviation from whole number\n",
    "                    'minlp_integer_tol 0.05', \\\n",
    "                    # covergence tolerance\n",
    "                    'minlp_gap_tol 0.01']\n",
    "\n",
    "# Initialize variables\n",
    "x1 = m.Var(value=1,lb=1,ub=5)\n",
    "x2 = m.Var(value=5,lb=1,ub=5)\n",
    "# Integer constraints for x3 and x4\n",
    "x3 = m.Var(value=5,lb=1,ub=5,integer=True)\n",
    "x4 = m.Var(value=1,lb=1,ub=5,integer=True)\n",
    "# Equations\n",
    "m.Equation(x1*x2*x3*x4>=25)\n",
    "m.Equation(x1**2+x2**2+x3**2+x4**2==40)\n",
    "m.Obj(x1*x4*(x1+x2+x3)+x3) # Objective\n",
    "m.solve(disp=False) # Solve\n",
    "print('Results')\n",
    "print('x1: ' + str(x1.value))\n",
    "print('x2: ' + str(x2.value))\n",
    "print('x3: ' + str(x3.value))\n",
    "print('x4: ' + str(x4.value))\n",
    "print('Objective: ' + str(m.options.objfcnval))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 11: Optimal Control with Integral Objective\n",
    "\n",
    "__Original Form__\n",
    "\n",
    "$\\min_u \\frac{1}{2} \\int_0^2 x_1^2(t) \\, dt$\n",
    "\n",
    "$\\mathrm{subject \\; to}$\n",
    "\n",
    "$\\frac{dx_1}{dt}=u$\n",
    "\n",
    "$x_1(0) = 1$\n",
    "\n",
    "$-1 \\le u(t) \\le 1$\n",
    "\n",
    "__Equivalent Form for GEKKO with new Variable $x_2$__\n",
    "\n",
    "$\\min_u x_2\\left(t_f\\right)$\n",
    "\n",
    "$\\mathrm{subject \\; to}$\n",
    "\n",
    "$\\frac{dx_1}{dt}=u$\n",
    "\n",
    "$\\frac{dx_2}{dt} = \\frac{1}{2} x_1^2(t)$\n",
    "\n",
    "$x_1(0) = 1$\n",
    "\n",
    "$x_2(0) = 0$\n",
    "\n",
    "$t_f = 2$\n",
    "\n",
    "$-1 \\le u(t) \\le 1$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x15f663b7710>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZQAAAEKCAYAAAA1qaOTAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xl8FdX9//HXh7CETURAVJACFithhyggiqJgUbRYqIpS\nqxVlqaCIG6hVUGnVCkoVpSC2+pUfiri2IAgqrVaQfQ1SEDeWCiIiW2T7/P6YS4kxIfcm997JTd7P\nx+M87izn3PkkDn4yc87MMXdHRESkqMqEHYCIiJQMSigiIhIXSigiIhIXSigiIhIXSigiIhIXSigi\nIhIXSigiIhIXSigiIhIXSigiIhIXZcMOIJlq1qzp9evXDzsMEZGUsmjRoq/dvVZB9UpVQqlfvz4L\nFy4MOwwRkZRiZp9HU0+3vEREJC6UUEREJC6UUEREJC5KVR+KiEii7d+/nw0bNpCdnR12KDFLT0+n\nbt26lCtXrlDtlVBEROJow4YNVK1alfr162NmYYcTNXdn27ZtbNiwgQYNGhTqO0K95WVmz5rZFjNb\nmc9+M7M/m9k6M1tuZq1z7OtqZmsi+4YmL2oRkfxlZ2dTo0aNlEomAGZGjRo1inRlFXYfyt+ArkfZ\nfyHQKFL6Ak8DmFkaMDayPwO40swyEhqpiEiUUi2ZHFbUuENNKO7+L+Cbo1TpDjzvgXnAsWZ2InAG\nsM7d17v7PuDFSN2E+Oc//8njjz/OwYMHE3UIEZGUF/YVSkHqAF/mWN8Q2Zbf9h8xs75mttDMFm7d\nurVQQUyZMoVbbrmFs846i6ysrEJ9h4hISVfcE0qRuft4d89098xatQp8c0CennzySSZNmsTatWtp\n2bIl999/P/v27YtzpCIi8dOpUydmzZoFwD333MOgQYMSfszinlA2AifnWK8b2Zbf9oQwM6666ipW\nr15Nz549ue+++8jMzGTBggWJOqSISJGMGDGCkSNHMmnSJJYsWcLjjz+e8GMW92HDbwIDzexFoC2w\nw903m9lWoJGZNSBIJL2AqxIdTK1atZg8eTJXXXUVAwYMoF27dgwZMoQRI0ZQqVKlRB9eRFLM4MGD\nWbp0aVy/s2XLllElh44dO+LujB49mjlz5pCWlsb69esZOXIkO3bsYOrUqXGNC8IfNjwZmAv8zMw2\nmFkfM+tvZv0jVaYD64F1wATgdwDufgAYCMwEVgNT3H1VsuK+5JJLWLVqFX369OHRRx+lRYsWzJkz\nJ1mHFxEp0IoVK9i8eTPly5enatWqADRs2JCJEycm7qDuXmpKmzZtPN7effddb9iwoQPer18/37Fj\nR9yPISKpIysrK+wQfNOmTd6sWTPPysryzp07+1tvvfWD/T179sy3bV7xAws9iv/HFvc+lGKvU6dO\nrFixgiFDhjBhwgSaNGnCtGnTwg5LREqpPXv20KNHD0aNGkXjxo35/e9/z4gRI5JybCWUOKhUqRKj\nRo3iww8/pFq1alx88cX8+te/5uuvvw47NBEpZSpVqsTcuXPp0qULEPSlzJ07F4Bt27bRv39/lixZ\nwh//+Me4H1sJJY7atm3L4sWLue+++5gyZQoZGRm89NJLBFeMIiLhqlGjBuPGjeOTTz5h2LBhcf9+\nJZQ4K1++PMOHD2fRokXUr1+fXr16cemll7JxY8JGNYuIFAtKKAnSrFkz5s6dy6OPPsqsWbPIyMhg\nwoQJuloRkRJLCSWB0tLSuPXWW1m+fDmtW7emb9++nH/++XzyySdhhyYiEndKKEnw05/+lHfffZfx\n48ezaNEimjVrxujRo/WySREpUZRQksTMuOGGG8jKyqJz587ceuutnHnmmaxcmedUMCIiKUcJJcnq\n1KnDG2+8weTJk1m/fj2tW7dmxIgRetmkiKQ8JZQQmBm9evVi9erVXH755QwfPpw2bdowf/78sEMT\nESk0JZQQ1axZkxdeeIF//OMffPvtt7Rv357bbruNPXv2hB2aiEjMlFCKgW7durFq1Sr69u3LqFGj\naN68Oe+9917YYYmIxEQJpZg45phjePrpp5kzZw5mxnnnnUffvn3ZsWNH2KGJSArSBFvCOeecw7Jl\ny7j99tuZOHEiGRkZ/P3vfw87LBFJMZpgS4Dg5W6PPPIIl19+Oddddx2/+MUv6NWrF2PGjOH4448P\nOzwRidLgwRDn+bVo2RKiyQ15TbD1+uuvM23aNL777jv69OnDBRdcENfYwp5gq6uZrTGzdWY2NI/9\nt5vZ0khZaWYHzey4yL7PzGxFZN/C5EefeJmZmSxcuJD777+fV155hYyMDCZNmqTXt4hIgfKaYOvS\nSy9lwoQJjBs3jpdeein+B41m0pREFCAN+ARoCJQHlgEZR6l/CfBujvXPgJqxHDMRE2wly8qVK71d\nu3YOeLdu3fyLL74IOyQRyUMqTLA1ZMgQX7RoUZ5tU3WCrTOAde6+3t33AS8C3Y9S/0pgclIiK4aa\nNGnCBx98wOOPP857771HkyZNGDduHIcOHQo7NBEpRo42wZa7c+edd3LhhRfSunXruB87zIRSB/gy\nx/qGyLYfMbNKQFfglRybHZhtZovMrG/CoixG0tLSuPnmm1m5ciVt27ZlwIABnHfeeaxduzbs0ESk\nmDjaBFtPPPEEs2fPZurUqYwbNy7ux06VUV6XAP92929ybDvL3VsCFwI3mlnHvBqaWV8zW2hmC7du\n3ZqMWBOuQYMGvP3220ycOJGlS5fSvHlz/vSnP3HgwIGwQxORYuymm25i0aJFjBs3jv79+8f9+8NM\nKBuBk3Os141sy0svct3ucveNkc8twGsEt9B+xN3Hu3umu2fWqlWryEEXF2bGddddR1ZWFl27duWO\nO+6gXbt2LFu2LOzQRKSUCjOhLAAamVkDMytPkDTezF3JzKoB5wBv5NhW2cyqHl4GLgBK5Wt7Tzrp\nJF599VWmTJnCl19+SWZmJr///e/5/vvvww5NREqZ0BKKux8ABgIzgdXAFHdfZWb9zSzntdgvgbfd\nfXeObbWBD8xsGTAfmObuM5IVe3FjZlx22WVkZWVx5ZVX8uCDD9KqVav/3TcVEUmGUPtQ3H26u5/q\n7qe4+8jItnHuPi5Hnb+5e69c7da7e4tIaXK4bWlXo0YNnn/+eaZPn86uXbvo0KEDgwcPZvfu3QU3\nFhEpolTplJcYXHjhhaxatYoBAwYwZswYmjZtyuzZs8MOS0RKOCWUEqpq1aqMHTuWf/3rX5QrV44u\nXbrQp08ftm/fHnZoIlJCKaGUcGeffTbLli3jzjvv5LnnniMjI4PXXnst7LBEpARSQikFKlasyEMP\nPcT8+fM54YQT6NGjB5dddhlfffVV2KGJSAmihFKKtG7dmvnz5zNy5EjefPNNGjduzPPPP6+XTYpI\nXCihlDLlypXjrrvuYtmyZTRu3JhrrrmGCy+8kM8//zzs0EQkjtq3b8+nn34KwMaNG2nTpk3Cj6n5\nUEqp0047jffff5+xY8cybNgwmjZtykMPPcSAAQMoU0Z/Z4jEzbnn/njbxRfDbbcVbv+cOQUe8tCh\nQ3z++efUr18fgOXLl9O8efMoAy48/Z+jFCtTpgyDBg1i5cqVnHnmmQwcOJBzzjmHNWvWhB2aiBTB\nJ598QoMGDTAzIEgozZo1S/hxdYUi1K9fnxkzZvDcc88xZMgQWrRowfDhw7n11lspV65c2OGJpLaC\nriiKuj8PK1as+EECWbhwIX37Jv6l7LpCESB4fcu1115LVlYWF198McOGDaNt27YsWbIk7NBEJEbf\nfPMNxx57LACrV69m2rRpuuUlyXfCCScwdepUpk6dyqZNmzj99NO5++67yc7ODjs0EYnSz3/+c2bM\nmEHv3r15+eWXqVGjBrVr1074ca00DRnNzMz0hQtL5PTzCbF9+3ZuvfVW/vrXv/Kzn/2MiRMn0qFD\nh7DDEinWVq9eTePGjcMOo9Dyit/MFrl7ZkFtdYUi+apevTrPPvssM2fOJDs7m7PPPpubbrqJXbt2\nhR2aiBRDSihSoAsuuICVK1cyaNAgnnzySZo2bcrMmTPDDktEihklFIlKlSpVGDNmDO+//z4VK1ak\na9euXHvttXzzzTcFNxaRUkEJRWLSoUMHlixZwt13382kSZNo3LgxU6dODTsskWIlVfumixp3qAnF\nzLqa2RozW2dmQ/PYf66Z7TCzpZFyb7RtJXHS09N58MEHWbBgAXXr1uWyyy6jZ8+ebN68OezQREKX\nnp7Otm3bUi6puDvbtm0jPT290N8R2igvM0sD/gN0ATYQzDF/pbtn5ahzLnCbu18ca9u8aJRX/B04\ncIDRo0dz7733UrFiRUaPHs211177vyd0RUqb/fv3s2HDhpQcap+enk7dunV/9EBztKO8wnxS/gxg\nnbuvBzCzF4HuwFGTQhzaShyVLVuWO+64g0svvZTrr7+e6667jsmTJzN+/Pj/vUdIpDQpV64cDRo0\nCDuMUIR5y6sO8GWO9Q2RbbmdaWbLzewtM2sSY1tJklNPPZU5c+bw1FNPMXfuXJo0acKf//xnDh48\nGHZoIpIkxb1TfjFQz92bA08Ar8f6BWbW18wWmtnCrVu3xj1AOaJMmTIMGDCAVatWcc4553DzzTfT\nsWNHVq9eHXZoIpIEYSaUjcDJOdbrRrb9j7t/5+67IsvTgXJmVjOatjm+Y7y7Z7p7Zq1ateIZv+Sj\nXr16TJs2jf/7v//j448/pmXLlowcOZL9+/eHHZqIJFCYCWUB0MjMGphZeaAX8GbOCmZ2gkV6d83s\nDIJ4t0XTVsJlZvz6178mKyuLSy+9lHvuuYfMzEwWLVoUdmgikiChJRR3PwAMBGYCq4Ep7r7KzPqb\nWf9ItV8BK81sGfBnoJcH8myb/J9CClK7dm1eeuklXnvtNbZs2ULbtm0ZOnQoe/fuDTs0EYkzvRxS\nkmb79u3cfvvtTJw4kVNPPZVnnnmGs88+O+ywRKQAejmkFDvVq1fnmWeeYdasWezbt4+OHTsycOBA\ndu7cGXZoIhIHSiiSdJ07d2blypUMHjyYp556iiZNmvDWW2+FHZaIFJESioSicuXKPPbYY/z73/+m\nSpUqXHTRRfzmN79h27ZtYYcmIoWkhCKhat++PUuWLOGee+5h8uTJNG7cmClTpqTce5BERAlFioEK\nFSrwwAMPsGjRIurVq8cVV1xBjx492LRpU9ihiUgMlFCk2GjevDnz5s3jkUceYcaMGWRkZDBx4kRd\nrYikCCUUKVbKli3L7bffzvLly2nRogXXX389Xbp0Yf369WGHJiIFUEKRYqlRo0a89957PP3008yf\nP59mzZrx+OOP62WTIsWYEooUW2XKlKF///5kZWXRqVMnbrnlFs466yyysjRLgUhxpIQixV7dunX5\n+9//zgsvvMDatWtp1aoVDzzwAPv27Qs7NBHJQQlFUoKZ0bt3b1avXk2PHj249957yczMZMGCBWGH\nJiIRSiiSUmrVqsXkyZN544032LZtG+3ateOOO+7QyyZFigElFElJv/jFL8jKyqJPnz786U9/onnz\n5vzzn/8MOyyRUk0JRVJWtWrVGD9+PO+88w6HDh3i3HPPpX///uzYsSPs0ERKJSUUSXnnnXceK1as\nYMiQIUyYMIEmTZowbdq0sMMSKXWUUKREqFSpEqNGjWLu3LlUr16diy++mN69e7N169awQxMpNUJN\nKGbW1czWmNk6Mxuax/7eZrbczFaY2Ydm1iLHvs8i25eamWbNEgDOOOMMFi1axPDhw3n55ZfJyMjg\nxRdf1OtbRJIgtIRiZmnAWOBCIAO40swyclX7FDjH3ZsBDwDjc+3v5O4to5lJTEqP8uXLc99997F4\n8WIaNmzIlVdeSffu3dm4cWPYoYmUaGFeoZwBrHP39e6+D3gR6J6zgrt/6O7bI6vzgLpJjlFSWNOm\nTfnwww8ZPXo0s2fPJiMjg/Hjx3Po0KGwQxMpkcJMKHWAL3Osb4hsy08fIOe0fg7MNrNFZtY3v0Zm\n1tfMFprZQt1PL33S0tK45ZZbWLFiBW3atKFfv36cf/75rFu3LuzQREqclOiUN7NOBAnlzhybz3L3\nlgS3zG40s455tXX38e6e6e6ZtWrVSkK0UhydcsopvPPOO0yYMIHFixfTvHlzRo0apZdNisRRmAll\nI3ByjvW6kW0/YGbNgWeA7u7+v/lh3X1j5HML8BrBLTSRfJkZ119/PVlZWXTu3JnbbruN9u3bs2LF\nirBDEykRwkwoC4BGZtbAzMoDvYA3c1Yws3rAq8DV7v6fHNsrm1nVw8vABcDKpEUuKa1OnTq88cYb\nvPjii3z22We0adOG4cOH62WTIkUUWkJx9wPAQGAmsBqY4u6rzKy/mfWPVLsXqAE8lWt4cG3gAzNb\nBswHprn7jCT/CJLCzIwrrriCrKwsLr/8ckaMGEHr1q356KOPwg5NJGVZaRqfn5mZ6QsX6pEV+bFp\n06bRv39/Nm3axODBg7n//vupXLly2GGJFAtmtiiaxzNSolNeJNG6devGqlWr6NevH6NHj6Z58+a8\n++67YYclklKUUEQijjnmGJ566inmzJlDmTJlOP/887nhhhv49ttvww5NJCXolpeknP37Yc8e2LsX\nsrN/WL7//kjZt+9I2b8/+DxwIFg+cOCH5eDB4PPQoWD5++8PMG/efJYsWUalSlXo0OFs6tWrz6FD\n4J5/OSy/ZZGwDB0KLVoUXC8v0d7yKlu4rxeJTXY2bN8elG+/PVJ27AjKd98FZefOoOzadaTs3h2U\nPXuCEu9HR8wgLS0oZctCmTKQllaWtLQzqV79dHbu3MGsWfupWHEb1asfS1paGmbkW3J+b17LImFI\nxqwOSihSKLt2wX//G5QtW+Crr4LPrVvh66+Dz23bjpSCJlQsWxaOOQaqVoUqVYLPqlWhdm2oXDko\nlSodKRUrBp/p6VChQrBeocIPS/nyR0q5csFn2bLBcrlywXJaWpBA8leO/fur8fDDD/PAAw+QnV2F\nMWPG0Lt3b0xZQuQHdMtLfuDQoSA5fPEFfPklbNgAGzcGn5s2BWXz5uCKIS/Vq0OtWlCzZlBq1IDj\njjtSjj02qHPssUGpVi0o6enF/6/4wzNEzps3j4suuohx48Zx8sknF9xQJMVFe8tLCaWUcQ+uGD75\nBNavD8qnn8JnnwXliy+CPoac0tPhpJOgTp3g88QTg3LCCUGpXRuOPz5IIOXKhfFTJc/Bgwd58skn\nueuuu0hLS+Phhx+mX79+lDn6ZY5ISlNCyUNpSig7d8KaNUH5z3+Cz3XrgpL7Xmrt2tCgAdSvD/Xq\nwU9+EnzWrQsnnxxcWRT3q4dk+/TTT+nbty+zZ8+mY8eOPPPMMzRq1CjssEQSIm4JxcxqA38ATnL3\nCyNzlrR394nxCTV5SmJC2bULVq6EVauOlKys4BbVYWXKBMmiUaOg/PSn0LAhnHJKsL1SpbCiT23u\nzt/+9jeGDBlCdnY2I0aMYMiQIZQtq65JKVnimVDeAv4K3O3uLcysLLAkMulVSknlhOIe3I5auvRI\nWb48uGV1WMWK0LgxZGTAaacFy6edFiSOChXCi72k27x5MzfeeCOvvfYabdq0YeLEibQo7PhMkWIo\nngllgbufbmZL3L1VZNvSyKvjU0qqJBT34ApjwYKgLFoEixcHfR8Q3H5q1CgYU96s2ZFSv34wakmS\nz9155ZVXuPHGG/nmm28YOnQo99xzDxWUyaUEiOdzKLvNrAbBhFaYWTsgCSOaS4/du4PEMW9eUD76\nKBiOC8HQ1mbN4NJLoXXroDRrFgyjleLDzPjVr35Fp06dGDJkCA8++CCvvPIKEydOpH379mGHJ5IU\n0VyhtAaeAJoSvCK+FvArd1+e+PDiq7hcoXz1Fbz/PnzwAfz737BkyZGH9U49Fdq2hTPOgNNPD65C\n0tPDjVdiN2PGDPr168eXX37JoEGDGDlyJFWqVAk7LJFCiesor0i/yc8AA9a4+/4CmhRLYSWUzZth\nzpwj5T+RmV0qVgySR4cOcOaZwXKNGkkPTxJk586dDBs2jLFjx1K/fn3Gjx9Ply5dwg5LJGbx7EP5\nTV7b3f35QsYWmmQllB07gsQxeza88w6sXh1sP+YY6NjxSGnduuQ/tyHwwQcfcP3117NmzRp++9vf\nMmrUKKpXrx52WCJRi2dCeSLHajpwPrDY3X9VtBDBzLoCY4A04Bl3fyjXfovsvwjYA1zr7oujaZuX\nRCWUQ4eCjvMZM2DmzKAf5ODBYDju2WfD+edDp07QqpU6zUur7Oxs7r//fh555BFq1arF2LFj6dGj\nR9hhiUQl2oSCu8dUgGOBGbG2y+N70oBPgIZAeWAZkJGrzkXAWwS32toBH0XbNq/Spk0bj5ft291f\nfNH96qvda9UK3jVr5p6Z6X7XXe5z5rhnZ8ftcFJCLF682Fu2bOmA9+zZ0zds2BB2SCIFAhZ6FP9f\nL8z7InYDDQrRLrczgHXuvt7d9wEvAt1z1ekOPB/5meYBx5rZiVG2jbvPPoMxY+C884L3VfXqBdOn\nQ5cu8MILQWf7ggUwciScc46e/ZAfa9WqFfPnz+cPf/gD06ZN47TTTuOxxx7jwIEDYYcmUmQFDhs2\ns78TGTJMMCFXBjAlDseuA3yZY30D0DaKOnWibBs3EyfCE0/AsmXBepMmcNttcMklQUe6bmNJLMqV\nK8ewYcO44oorGDhwIEOGDOGJJ57gJz/5CZUqVSI9PR0zo+aePVyzfDlphw7hZjjwRbVqTMnIAKDP\nkiUc+/33P/juL485Rvu1/0f75590Eh3/8hdatWpFIkXzHMqjOZYPAJ+7+4b8Khc3ZtYX6AtQr169\nQn3Haf93N9M/nszkR9fTvXvw6hKRomrYsCHTpk3j1Vdf5dlnn2Xnzp189dVXZGdnA3D/xo202bGD\n9RUqUMYdAzbt2cPHkRdRVtmyhZq53uT53927tV/7f7Q/+8ABduf3ivA4Cu3lkGbWHhju7j+PrA8D\ncPc/5qjzF2COu0+OrK8BzgXqF9Q2L4XtlPfbbseeGhvM7iSSLFu3wvz50K1b2JFIKRdtp3y+fShm\nttPMvsuj7DSz7+IQ4wKgkZk1MLPyQC/gzVx13gR+Y4F2wA533xxl27ixiunBlIOl6M3MUgzUqqVk\nIikl34Ti7lXd/Zg8SlV3P6aoB3b3A8BAYCawGpji7qvMrL+Z9Y9Umw6sB9YBE4DfHa1tUWPKV3p6\nkExyTxQikgjLl0P79sGcAyIpJOr3bJvZ8QTPoQDg7l8U9eDuPp0gaeTcNi7HsgM3Rts2YQ6/+yQ7\nO5hHViSR7rsveBr2+OPDjkQkJgUOGzazX5jZWuBT4J/AZwTPhpQep50Gvyryc5wiBVu2DF5/HYYM\nCeZKFkkh0TyH8gDBQ4X/cfcGBE/Kz0toVMVNt27w8svBu1NEEmnx4uCzd+9w4xAphGgSyn533waU\nMbMy7v4eUPAj+CISu717g0+9mVhSUDQJ5VszqwK8D0wyszEET8uXHtOmBROrr0pcv78IEMxfcO21\nULVq2JGIxCzfTnkzGwtMJnilyV5gMNAbqAbcn5Toigt32L5dz6FI4nXuHBSRFHS0UV7/Af4EnEjw\nqpXJ7v5cUqIqbnKO8hJJJPdgjmeRFHS051DGuHt74BxgG/CsmX1sZvea2alJi7A4UEKRZLn1Vo3u\nkpRVYB+Ku3/u7g+7eyvgSuCXBA8Tlh5KKJIs2dlQNurHw0SKlWieQylrZpeY2SSC50/WAKVrZqCa\nNaFHDz1oJom3d28wN7RICjpap3wXgiuSi4D5BHOO9HX30jXCC6B+fXjllbCjkNJACUVS2NGurYcB\n/w+41d23JykekdJNCUVS2NE65c9z92eUTIBvvoEaNeAvfwk7EinpOneGnj3DjkKkUNT7F41y5YKk\nsnNn2JFISTdoUNgRiBRaYeaUL300ykuS5dChsCMQKTQllGiULQtlyiihSOI1awa9eoUdhUihKKFE\nwyy4SlFCkUTbuze4xSqSgkJJKGZ2nJnNMrO1kc8fPRpsZieb2XtmlmVmq8zs5hz7hpvZRjNbGikX\nJTzonj2hadOEH0ZKuexsjfKSlBVWp/xQ4B13f8jMhkbW78xV5wDBkOXFZlYVWGRms9w9K7L/MXd/\nNGkRP/980g4lpZiGDUsKC+uWV3fg8IsmnwMuzV3B3Te7++LI8k6C173USVqEImFQQpEUFlZCqe3u\nmyPL/wVqH62ymdUHWgEf5dg8yMyWm9mzed0yi7sOHeDqqxN+GCnF3IO5UNq2DTsSkUJJ2C0vM5sN\nnJDHrrtzrri7m5kf5XuqAK8Ag939u8jmpwmmJvbI5yjgunza9wX6AtSrVy/GnyKH7Gz49tvCtxcp\niBmMGxd2FCKFlrCE4u75zhJkZl+Z2YnuvtnMTgS25FOvHEEymeTur+b47q9y1JkA/OMocYwHxgNk\nZmbmm7gKVKGCRnlJYrkHpYwGX0pqCuvMfRO4JrJ8DfBG7gpmZsBEYLW7j86178Qcq78EViYoziM0\nbFgSbcMGSEuDiRPDjkSkUMJKKA8BXcxsLdA5so6ZnWRm0yN1OgBXA+flMTz4ETNbYWbLgU7ALQmP\nWAlFEm3v3uCzQoVw4xAppFCGDbv7NuD8PLZvInhdPu7+AZDnXKjunvze8XPOgW3bkn5YKUUOJxSN\n8pIUpZdDRuvO3I/JiMTZ4StgJRRJUer9EykudIUiKU4JJVp33AENG4YdhZRktWvDDTfAySeHHYlI\noeiWV7QOHICvvw47CinJGjeG8ePDjkKk0HSFEi09hyKJdvBg8ByKSIpSQolWejrs3x/8oxdJhL/+\nNXioccOGsCMRKRQllGgdnrXx++/DjUNKrsOd8ofPNZEUo4QSrSZN4IordEtCEkejvCTFqVM+Whdf\nHBSRRNFzKJLidIUiUlzs3Qvly+vlkJKydOZG6/XXoVo1+PjjsCORkur006Ffv7CjECk03fKKlhl8\n992R+9wi8dajR1BEUpSuUKJ1+A2wehZFEuXAAQ36kJSmhBKtw0M5lVAkUXr1gqZNw45CpNCUUKKl\nhCKJtnevnkGRlKaEEq3jj4fLLw8+RRJh714NGZaUFkqnvJkdB7wE1Ac+Ay539+151PsM2AkcBA64\ne2Ys7eO4pV6QAAAM8ElEQVSqYUN46aWEHkJKub17oUqVsKMQKbSwrlCGAu+4eyPgnch6fjq5e8vD\nyaQQ7UVSQ3a2rlAkpYWVULoDz0WWnwMuTXL72G3ZAsceCxMmJPxQUkr17AnduoUdhUihhfUcSm13\n3xxZ/i9QO596Dsw2s4PAX9z98GQR0bbHzPoCfQHq1atX+IjLl4cdO2D37sJ/h8jR3HNP2BGIFEnC\nEoqZzQZOyGPX3TlX3N3NLL/B92e5+0YzOx6YZWYfu/u/YmhPJAmNB8jMzCz8IH89hyKJtm8flCsX\nPEQrkoISdsvL3Tu7e9M8yhvAV2Z2IkDkc0s+37Ex8rkFeA04I7IrqvZxpYQiiVajBtx2W9hRiBRa\nWH0obwLXRJavAd7IXcHMKptZ1cPLwAXAymjbx12ZMsFtLyUUSRQ9hyIpLqyE8hDQxczWAp0j65jZ\nSWY2PVKnNvCBmS0D5gPT3H3G0donnJ5klkQ5PBuoRnlJCgulU97dtwHn57F9E3BRZHk90CKW9gn3\n3HMF1xEpDE2uJSWAnpQXKQ6UUKQEUEKJxemnwzXXFFxPJFbly8PvfgfNm4cdiUihaT6UWOzbF8yJ\nIhJv1avD2LFhRyFSJLpCiUV6ukZ5SWIcPBh0zIukMCWUWCihSKLMmxfc9po5M+xIRApNCSUWSiiS\nKOqUlxJAfSixOO882Lkz7CikJFJCkRJACSUWd94ZdgRSUimhSAmgW14ixYESipQASiixGDw4mLlR\nJN5OPRUGDIDjjgs7EpFC0y2vWBw6BN9+G3YUUhK1bx8UkRSmK5RYaJSXJMr+/XDgQNhRiBSJEkos\nDicUL/w8XSJ5euCBYHItnVuSwpRQYpGeHvyD1xPNEm979wYd8pqtUVKYEkosmjWD3r2DvhSReDqc\nUERSmDrlY3HJJUERiTclFCkBQrlCMbPjzGyWma2NfFbPo87PzGxpjvKdmQ2O7BtuZhtz7Lso+T+F\nSBwpoUgJENYtr6HAO+7eCHgnsv4D7r7G3Vu6e0ugDbAHeC1HlccO73f36bnbJ8TLL0PlyrB2bVIO\nJ6VIly6aa0dSXli3vLoD50aWnwPmAEd7r8n5wCfu/nliwypAmTKwZ4+GDkv8/fa3YUcgUmRhXaHU\ndvfNkeX/ArULqN8LmJxr2yAzW25mz+Z1y+wwM+trZgvNbOHWrVuLEDLBKC9QQpH4y84O5kQRSWEJ\nSyhmNtvMVuZRuues5+4O5Dv43szKA78AXs6x+WmgIdAS2AyMyq+9u49390x3z6xVq1ZRfiQlFEmc\njh2hW7ewoxApkoTd8nL3zvntM7OvzOxEd99sZicCW47yVRcCi939qxzf/b9lM5sA/CMeMRdICUUS\nRZ3yUgKEdcvrTeBwD+Q1wBtHqXsluW53RZLQYb8EVsY1uvyccAJcdRUU9UpHJDclFCkBwuqUfwiY\nYmZ9gM+BywHM7CTgGXe/KLJeGegC9MvV/hEza0lwq+yzPPYnximnwKRJSTmUlDJKKFIChJJQ3H0b\nwcit3Ns3ARflWN8N1Mij3tUJDVAk2ZRQpATQq1disXkzVKkCzz4bdiRS0txwA3TqFHYUIkWiV6/E\nonx52L07eBZFJJ4efjjsCESKTFcosdAoL0kE9+APFb10VFKcEkosKlQIPpVQJJ6+/Ta4lfrEE2FH\nIlIkSiixKFsW0tKUUCS+9u4NPg9fAYukKCWUWF19dTAviki8HE4oGuUlKU6d8rH661/DjkBKGiUU\nKSF0hSISNiUUKSGUUGLVogVce23YUUhJUrMm3HRT8CYGkRSmW16xOngwGOIpEi8NGsCYMWFHIVJk\nukKJVXq6RnlJfO3fH9z28nxncRBJCUoosapQ4cg9b5F4mDoVKlWCNWvCjkSkSJRQYqUrFIk3dcpL\nCaE+lFhdcIESisTXq69CtWpw/PFhRyJSJEoosbrzzrAjkJLk/fdh2jT44x91hSIpL5RbXmZ2mZmt\nMrNDZpZ5lHpdzWyNma0zs6E5th9nZrPMbG3ks3pyIheJswcegJNOCoYNi6S4sPpQVgI9gH/lV8HM\n0oCxBHPKZwBXmllGZPdQ4B13bwS8E1lPjt/9Dho2TNrhpIR74QWYMiXolBdJcWHN2LgawMyOVu0M\nYJ27r4/UfRHoDmRFPs+N1HsOmAMk717Url1JO5SUUIcOgVnQb6K+EykhinMfSh3gyxzrG4C2keXa\n7r45svxfoHbSokpPh6+/hiZN4JhjYO7cYPvgwTBr1g/ran/p2v/22z/cX63akf033xzsP3gQvv8e\nNm2C5s1hxgyoVQuRkiBhCcXMZgMn5LHrbnd/I17HcXc3s3yfCDOzvkBfgHr16hX9gFdeCRs3Bn9h\nVqlyZPvJJ0NGxg/ran/p2t+kSXDVcVjlykeWf/KTIIGUKRM8y5SeDo0bB69dESkhzEN8OtfM5gC3\nufvCPPa1B4a7+88j68MA3P2PZrYGONfdN5vZicAcd/9ZQcfLzMz0hQt/dCgRETkKM1vk7vkOoDqs\nOD/YuABoZGYNzKw80At4M7LvTeCayPI1QNyueEREpHDCGjb8SzPbALQHppnZzMj2k8xsOoC7HwAG\nAjOB1cAUd18V+YqHgC5mthboHFkXEZEQhXrLK9l0y0tEJHYl4ZaXiIikECUUERGJCyUUERGJCyUU\nERGJCyUUERGJi1I1ysvMtgKfF7J5TeDrOIYTL4orNoorNoorNsU1LihabD9x9wLfEVSqEkpRmNnC\naIbNJZviio3iio3iik1xjQuSE5tueYmISFwooYiISFwooURvfNgB5ENxxUZxxUZxxaa4xgVJiE19\nKCIiEhe6QhERkbhQQgHMrKuZrTGzdWb2o/npLfDnyP7lZtY62rYJjqt3JJ4VZvahmbXIse+zyPal\nZhbXN2JGEde5ZrYjcuylZnZvtG0THNftOWJaaWYHzey4yL6E/L7M7Fkz22JmK/PZH9a5VVBcYZ1b\nBcUV1rlVUFxJP7ci332ymb1nZllmtsrMbs6jTvLOMXcv1QVIAz4BGgLlgWVARq46FwFvAQa0Az6K\ntm2C4zoTqB5ZvvBwXJH1z4CaIf2+zgX+UZi2iYwrV/1LgHeT8PvqCLQGVuazP+nnVpRxJf3cijKu\npJ9b0cQVxrkV+e4TgdaR5arAf8L8/5euUOAMYJ27r3f3fcCLQPdcdboDz3tgHnCsBTNFRtM2YXG5\n+4fuvj2yOg+oG6djFymuBLWN93dfCUyO07Hz5e7/Ar45SpUwzq0C4wrp3Irm95WfUH9fuSTl3AJw\n983uvjiyvJNg7qg6uaol7RxTQgl++V/mWN/Aj/+D5FcnmraJjCunPgR/hRzmwGwzW2RmfeMUUyxx\nnRm5vH7LzJrE2DaRcWFmlYCuwCs5Nifq91WQMM6tWCXr3IpWss+tqIV5bplZfaAV8FGuXUk7x8oW\npbEUD2bWieAf/Vk5Np/l7hvN7Hhglpl9HPkrKxkWA/XcfZeZXQS8DjRK0rGjcQnwb3fP+RdnmL+v\nYkvnVsxCObfMrApBEhvs7t/F87tjoSsU2AicnGO9bmRbNHWiaZvIuDCz5sAzQHd333Z4u7tvjHxu\nAV4juLxNSlzu/p2774osTwfKmVnNaNomMq4cepHrlkQCf18FCePcikoI51aBQjq3YpH0c8vMyhEk\nk0nu/moeVZJ3jiWioyiVCsFV2nqgAUc6pprkqtONH3ZqzY+2bYLjqgesA87Mtb0yUDXH8odA1yTG\ndQJHnnE6A/gi8rsL9fcVqVeN4F545WT8viLfWZ/8O5mTfm5FGVfSz60o40r6uRVNXCGeWwY8Dzx+\nlDpJO8dK/S0vdz9gZgOBmQSjHp5191Vm1j+yfxwwnWCkxDpgD/Dbo7VNYlz3AjWAp8wM4IAHL3+r\nDbwW2VYW+H/uPiOJcf0KGGBmB4C9QC8PzuCwf18AvwTedvfdOZon7PdlZpMJRibVNLMNwH1AuRwx\nJf3cijKupJ9bUcaV9HMryrggyedWRAfgamCFmS2NbLuL4A+CpJ9jelJeRETiQn0oIiISF0ooIiIS\nF0ooIiISF0ooIiISF0ooIiISF6V+2LBIIphZDeCdyOoJwEFga2R9j7ufGUpgIgmkYcMiCWZmw4Fd\n7v5o2LGIJJJueYkkmZntinyea2b/NLM3zGy9mT0UmYdkfmT+jFMi9WqZ2StmtiBSOoT7E4jkTQlF\nJFwtgP5AY4Innk919zMI3qE1KFJnDPCYu58O9IzsEyl21IciEq4F7r4ZwMw+Ad6ObF8BdIosdwYy\nIq/vADjGzKp45CWJIsWFEopIuL7PsXwox/ohjvz7LAO0c/fsZAYmEivd8hIp/t7myO0vzKxliLGI\n5EsJRaT4uwnIjMxSmEXQ5yJS7GjYsIiIxIWuUEREJC6UUEREJC6UUEREJC6UUEREJC6UUEREJC6U\nUEREJC6UUEREJC6UUEREJC7+P1lGcF7XGuSmAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f6559d668>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from gekko import GEKKO\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "m = GEKKO() # initialize gekko\n",
    "nt = 101\n",
    "m.time = np.linspace(0,2,nt)\n",
    "# Variables\n",
    "x1 = m.Var(value=1)\n",
    "x2 = m.Var(value=0)\n",
    "u = m.Var(value=0,lb=-1,ub=1)\n",
    "p = np.zeros(nt) # mark final time point\n",
    "p[-1] = 1.0\n",
    "final = m.Param(value=p)\n",
    "# Equations\n",
    "m.Equation(x1.dt()==u)\n",
    "m.Equation(x2.dt()==0.5*x1**2)\n",
    "m.Obj(x2*final) # Objective function\n",
    "m.options.IMODE = 6 # optimal control mode\n",
    "m.solve(disp=False) # solve\n",
    "plt.figure(1) # plot results\n",
    "plt.plot(m.time,x1.value,'k-',label=r'$x_1$')\n",
    "plt.plot(m.time,x2.value,'b-',label=r'$x_2$')\n",
    "plt.plot(m.time,u.value,'r--',label=r'$u$')\n",
    "plt.legend(loc='best')\n",
    "plt.xlabel('Time')\n",
    "plt.ylabel('Value')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 12: Optimal Control with Economic Objective\n",
    "\n",
    "__Original Form__\n",
    "\n",
    "$\\max_{u(t)} \\int_0^{10} \\left(E-\\frac{c}{x}\\right) u \\, U_{max} \\, dt$\n",
    "\n",
    "$\\mathrm{subject \\; to}$\n",
    "\n",
    "$\\frac{dx}{dt}=r \\, x(t) \\left(1-\\frac{x(t)}{k}\\right)-u \\, U_{max}$\n",
    "\n",
    "$x(0) = 70$\n",
    "\n",
    "$0 \\le u(t) \\le 1$\n",
    "\n",
    "$E=1, \\, c=17.5, \\, r=0.71$\n",
    "\n",
    "$k=80.5, \\, U_{max}=20$\n",
    "\n",
    "__Equivalent Form for GEKKO__\n",
    "\n",
    "$\\min_{u(t)} -J\\left(t_f\\right)$\n",
    "\n",
    "$\\mathrm{subject \\; to}$\n",
    "\n",
    "$\\frac{dx}{dt}=r \\, x(t) \\left(1-\\frac{x(t)}{k}\\right)-u \\, U_{max}$\n",
    "\n",
    "$\\frac{dJ}{dt} = \\left(E-\\frac{c}{x}\\right) u \\, U_{max}$\n",
    "\n",
    "$x(0) = 70$\n",
    "\n",
    "$J(0) = 0$\n",
    "\n",
    "$0 \\le u(t) \\le 1$\n",
    "\n",
    "$t_f = 10, \\, E=1, \\, c=17.5$\n",
    "\n",
    "$r=0.71, \\, k=80.5, \\, U_{max}=20$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Optimal Profit: 106.9061\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x15f687b56a0>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n7yNeAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f686e9860>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from gekko import GEKKO\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "# create GEKKO model\n",
    "m = GEKKO()\n",
    "# time points\n",
    "n=501\n",
    "m.time = np.linspace(0,10,n)\n",
    "# constants\n",
    "E,c,r,k,U_max = 1,17.5,0.71,80.5,20\n",
    "# fishing rate\n",
    "u = m.MV(value=1,lb=0,ub=1)\n",
    "u.STATUS = 1\n",
    "u.DCOST = 0\n",
    "x = m.Var(value=70) # fish population\n",
    "# fish population balance\n",
    "m.Equation(x.dt() == r*x*(1-x/k)-u*U_max)\n",
    "J = m.Var(value=0) # objective (profit)\n",
    "Jf = m.FV() # final objective\n",
    "Jf.STATUS = 1\n",
    "m.Connection(Jf,J,pos2='end')\n",
    "m.Equation(J.dt() == (E-c/x)*u*U_max)\n",
    "m.Obj(-Jf) # maximize profit\n",
    "m.options.IMODE = 6  # optimal control\n",
    "m.options.NODES = 3  # collocation nodes\n",
    "m.options.SOLVER = 3 # solver (IPOPT)\n",
    "m.solve(disp=False) # Solve\n",
    "print('Optimal Profit: ' + str(Jf.value[0]))\n",
    "plt.figure(1) # plot results\n",
    "plt.subplot(2,1,1)\n",
    "plt.plot(m.time,J.value,'r--',label='profit')\n",
    "plt.plot(m.time,x.value,'b-',label='fish')\n",
    "plt.legend()\n",
    "plt.subplot(2,1,2)\n",
    "plt.plot(m.time,u.value,'k--',label='rate')\n",
    "plt.xlabel('Time (yr)')\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 13: Optimal Control: Minimize Final Time\n",
    "\n",
    "__Original Form__\n",
    "\n",
    "$\\min_{u(t)} \\; t_f$\n",
    "\n",
    "$\\mathrm{subject \\; to}$\n",
    "\n",
    "$\\frac{dx_1}{dt}=u$\n",
    "\n",
    "$\\frac{dx_2}{dt}=\\cos\\left(x_1(t)\\right)$\n",
    "\n",
    "$\\frac{dx_3}{dt}=\\sin\\left(x_1(t)\\right)$\n",
    "\n",
    "$x(0) = \\left[\\pi/2,4,0\\right]$\n",
    "\n",
    "$x_2\\left(t_f\\right)=0$\n",
    "\n",
    "$x_3\\left(t_f\\right)=0$\n",
    "\n",
    "$-2 \\le u(t) \\le 2$\n",
    "\n",
    "__Equivalent Form for GEKKO__\n",
    "\n",
    "$\\min_{u(t), t_f} \\; t_f$\n",
    "\n",
    "$\\mathrm{subject \\; to}$\n",
    "\n",
    "$\\frac{dx_1}{dt}=t_f \\, u$\n",
    "\n",
    "$\\frac{dx_2}{dt}=t_f \\, \\cos\\left(x_1(t)\\right)$\n",
    "\n",
    "$\\frac{dx_3}{dt}=t_f \\, \\sin\\left(x_1(t)\\right)$\n",
    "\n",
    "$x(0) = \\left[\\pi/2,4,0\\right]$\n",
    "\n",
    "$x_2\\left(t_f\\right)=0$\n",
    "\n",
    "$x_3\\left(t_f\\right)=0$\n",
    "\n",
    "$-2 \\le u(t) \\le 2$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Final Time: 4.316256\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x15f68817518>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f65c24fd0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from gekko import GEKKO\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "m = GEKKO() # initialize GEKKO\n",
    "nt = 501\n",
    "m.time = np.linspace(0,1,nt)\n",
    "# Variables\n",
    "x1 = m.Var(value=np.pi/2.0)\n",
    "x2 = m.Var(value=4.0)\n",
    "x3 = m.Var(value=0.0)\n",
    "p = np.zeros(nt) # final time = 1\n",
    "p[-1] = 1.0\n",
    "final = m.Param(value=p)\n",
    "# optimize final time\n",
    "tf = m.FV(value=1.0,lb=0.1,ub=100.0)\n",
    "tf.STATUS = 1\n",
    "# control changes every time period\n",
    "u = m.MV(value=0,lb=-2,ub=2)\n",
    "u.STATUS = 1\n",
    "m.Equation(x1.dt()==u*tf)\n",
    "m.Equation(x2.dt()==m.cos(x1)*tf)\n",
    "m.Equation(x3.dt()==m.sin(x1)*tf)\n",
    "m.Equation(x2*final<=0)\n",
    "m.Equation(x3*final<=0)\n",
    "m.Obj(tf)\n",
    "m.options.IMODE = 6\n",
    "m.solve(disp=False)\n",
    "print('Final Time: ' + str(tf.value[0]))\n",
    "tm = np.linspace(0,tf.value[0],nt)\n",
    "plt.figure(1)\n",
    "plt.plot(tm,x1.value,'k-',label=r'$x_1$')\n",
    "plt.plot(tm,x2.value,'b-',label=r'$x_2$')\n",
    "plt.plot(tm,x3.value,'g--',label=r'$x_3$')\n",
    "plt.plot(tm,u.value,'r--',label=r'$u$')\n",
    "plt.legend(loc='best')\n",
    "plt.xlabel('Time')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 14: PID Control Tuning\n",
    "\n",
    "A [PID Controller](https://en.wikipedia.org/wiki/PID_controller) has proportional, integral, and derivative terms to determine the controller output ($OP$) based on the set point ($SP$) and process variable ($PV$). A standard PID form has constants $K_c$, $\\tau_I$, and $\\tau_D$.\n",
    "\n",
    "\n",
    "$err = SP-PV$\n",
    "\n",
    "$OP = OP_0 + K_c \\, err + \\frac{K_c}{\\tau_I} \\int err \\, dt - K_c \\, \\tau_D \\frac{d\\,PV}{dt}$ \n",
    "\n",
    "The effect of the tuning constants is shown with the [PID Tuning Notebook](http://nbviewer.jupyter.org/url/apmonitor.com/pdc/uploads/Main/pid_widget.ipynb). This example is an alternative implementation in GEKKO."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x15f699b3b70>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nl1LwoxNTMekAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f69918a90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from gekko import GEKKO\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "m = GEKKO()\n",
    "tf = 40\n",
    "m.time = np.linspace(0,tf,2*tf+1)\n",
    "step = np.zeros(2*tf+1)\n",
    "step[3:40] = 2.0\n",
    "step[40:]  = 5.0\n",
    "\n",
    "# Controller model\n",
    "Kc = 15.0                    # controller gain\n",
    "tauI = 2.0                  # controller reset time\n",
    "tauD = 1.0                  # derivative constant\n",
    "OP_0 = m.Const(value=0.0)   # OP bias\n",
    "OP = m.Var(value=0.0)       # controller output\n",
    "PV = m.Var(value=0.0)       # process variable\n",
    "SP = m.Param(value=step)    # set point\n",
    "Intgl = m.Var(value=0.0)    # integral of the error\n",
    "err = m.Intermediate(SP-PV) # set point error\n",
    "m.Equation(Intgl.dt()==err) # integral of the error\n",
    "m.Equation(OP == OP_0 + Kc*err + (Kc/tauI)*Intgl - PV.dt())\n",
    "\n",
    "# Process model\n",
    "Kp = 0.5                    # process gain\n",
    "tauP = 10.0                 # process time constant\n",
    "m.Equation(tauP*PV.dt() + PV == Kp*OP)\n",
    "\n",
    "m.options.IMODE=4\n",
    "m.solve(disp=False)\n",
    "\n",
    "plt.figure()\n",
    "plt.subplot(2,1,1)\n",
    "plt.plot(m.time,OP.value,'b:',label='OP')\n",
    "plt.ylabel('Output')\n",
    "plt.legend()\n",
    "plt.subplot(2,1,2)\n",
    "plt.plot(m.time,SP.value,'k-',label='SP')\n",
    "plt.plot(m.time,PV.value,'r--',label='PV')\n",
    "plt.xlabel('Time (sec)')\n",
    "plt.ylabel('Process')\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 15: Process Simulator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x15f69a82080>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nadP46aefSElJITw8POf5PP/88yQnJ7Nq1Sq+//57Vq1axYEDB5g5cyZr165l1apV57xJKFWYbt3g\no4+gmNU0VCFKbnLfvr1o9/tZrVq1aN++PQB9+/Zl8eLFxT5W3rLA/fv357///S8A//3vf3M+aUD+\nJYHBLvYBtiRww4YNqV69OqVLl+bSSy9lx44dLFiwgOXLl9O6dWuaNWvGggUL2LJlCwCffvopLVq0\noHnz5qxdu5Z169YRGxtLVFQU9957LzNmzCAmJqbYz1GFnp077RqlyjdKbnKvXbto93sgISEhp6pj\ntqNHj7J9+3bq1q1baDne3HKXBM69nfsYBf18bnnLArdv355t27axaNEiMjMzadSo0TkxuSsJDJxT\nBjh3OePsssAiwl133UVKSgopKSls2LCBp59+mq1bt/LKK6+wYMECVq1aRbdu3Th58iSlSpVi6dKl\n9O7dm6+//loX81BF8txzdsFo5RslN7k//zzkbSnGxNj7i6lz586kpaXx4YcfAnZZuuHDh9OvXz9i\nYmIKLMcbERGR0w8OsH379pxFPD7++GOuvvpq4NyywJ9//nnO/gWVBW7QoMF53UJ33nknt99++zmt\ndrD987mTfVGf//Tp0/nzzz8BOHjwIKmpqRw9epQyZcoQGxvL3r17+eabbwC7PN+RI0fo2rUr48aN\n47fffivWeVVoSks7/19YeU/JTe6JiXZljrg4MMZ+ffdde38xGWOYOXMmn332GfXq1ePyyy8nKioq\nZyRM7nK8Dz744DnleAcMGECTJk1IdJ3/iiuu4K233qJBgwYcOnSIQYMGATB69GiGDh1Kq1atCA8P\nz/n57t27M3PmTLcXVP/yl7+wcuVKclfwTExM5NChQzkrQgFkZGSwefNmWrUqtGCcWwkJCYwZM4a/\n/vWvNGnShOuvv57du3fTtGlTmjdvTv369bn99ttzupuOHTvGjTfeSJMmTbj66qt59dVXi3VeFZo+\n+ADWrHE6iuClJX99YNu2bdx4442s8eJf7tChQ+nevTvXXXcdANOnT+fLL7/ko48+ytknex3U5557\nzmvn9bZgeY2VcoqW/A0yTzzxBL/++itgx7N/8803zJkz55x9zpw5w/Dhw50IT6kiGzgQIiPhP/9x\nOpLgpC135Vf6GqtsbdvaEgSuSzjKQ9pyV0oFtOHDbclf5Rua3JVSjujTx+kIglvJHS2jlCrRkpLA\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f699fd7f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from gekko import GEKKO\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "# Generate \"data\" with process simulation\n",
    "nt = 51\n",
    "# input steps\n",
    "u_meas = np.zeros(nt)\n",
    "u_meas[3:10] = 1.0\n",
    "u_meas[10:20] = 2.0\n",
    "u_meas[20:40] = 0.5\n",
    "u_meas[40:] = 3.0\n",
    "# simulation model\n",
    "p = GEKKO()\n",
    "p.time = np.linspace(0,10,nt)\n",
    "n = 1 #process model order\n",
    "# Parameters\n",
    "steps = np.zeros(n)\n",
    "p.u = p.MV(value=u_meas)\n",
    "p.u.FSTATUS=1\n",
    "p.K = p.Param(value=1) #gain\n",
    "p.tau = p.Param(value=5) #time constant\n",
    "# Intermediate\n",
    "p.x = [p.Intermediate(p.u)]\n",
    "# Variables\n",
    "p.x.extend([p.Var() for _ in range(n)])  #state variables\n",
    "p.y = p.SV() #measurement\n",
    "# Equations\n",
    "p.Equations([p.tau/n * p.x[i+1].dt() == -p.x[i+1] + p.x[i] for i in range(n)])\n",
    "p.Equation(p.y == p.K * p.x[n])\n",
    "# Simulate\n",
    "p.options.IMODE = 4\n",
    "p.solve(disp=False)\n",
    "# add measurement noise\n",
    "y_meas = (np.random.rand(nt)-0.5)*0.2\n",
    "for i in range(nt):\n",
    "    y_meas[i] += p.y.value[i]\n",
    "plt.plot(p.time,u_meas,'b:',label='Input (u) meas')\n",
    "plt.plot(p.time,y_meas,'ro',label='Output (y) meas')\n",
    "plt.plot(p.time,p.y.value,'k-',label='Output (y) actual')\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 16: Moving Horizon Estimation\n",
    "\n",
    "Run the Process Simulation cell above to generate the data. The MHE application uses a first order model while the process simulation is a second order system. This is done to emulate a realistic case with model mismatch and measurement noise.\n",
    "\n",
    "This demonstrates just one cycle of an MHE application. Typical MHE applications receive an additional measurements, re-optimize parameters and states, and re-inject the parameters into a controller. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x15f69b5b358>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f688c2c50>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from gekko import GEKKO\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "# Estimator Model\n",
    "m = GEKKO()\n",
    "m.time = p.time\n",
    "# Parameters\n",
    "m.u = m.MV(value=u_meas) #input\n",
    "m.K = m.FV(value=1, lb=1, ub=3)    # gain\n",
    "m.tau = m.FV(value=5, lb=1, ub=10) # time constant\n",
    "# Variables\n",
    "m.x = m.SV() #state variable\n",
    "m.y = m.CV(value=y_meas) #measurement\n",
    "# Equations\n",
    "m.Equations([m.tau * m.x.dt() == -m.x + m.u, \n",
    "             m.y == m.K * m.x])\n",
    "# Options\n",
    "m.options.IMODE = 5 #MHE\n",
    "m.options.EV_TYPE = 1\n",
    "# STATUS = 0, optimizer doesn't adjust value\n",
    "# STATUS = 1, optimizer can adjust\n",
    "m.u.STATUS = 0\n",
    "m.K.STATUS = 1\n",
    "m.tau.STATUS = 1\n",
    "m.y.STATUS = 1\n",
    "# FSTATUS = 0, no measurement\n",
    "# FSTATUS = 1, measurement used to update model\n",
    "m.u.FSTATUS = 1\n",
    "m.K.FSTATUS = 0\n",
    "m.tau.FSTATUS = 0\n",
    "m.y.FSTATUS = 1\n",
    "# DMAX = maximum movement each cycle\n",
    "m.K.DMAX = 2.0\n",
    "m.tau.DMAX = 4.0\n",
    "# MEAS_GAP = dead-band for measurement / model mismatch\n",
    "m.y.MEAS_GAP = 0.25\n",
    "\n",
    "# solve\n",
    "m.solve(disp=False)\n",
    "\n",
    "# Plot results\n",
    "plt.subplot(2,1,1)\n",
    "plt.plot(m.time,u_meas,'b:',label='Input (u) meas')\n",
    "plt.legend()\n",
    "plt.subplot(2,1,2)\n",
    "plt.plot(m.time,y_meas,'gx',label='Output (y) meas')\n",
    "plt.plot(p.time,p.y.value,'k-',label='Output (y) actual')\n",
    "plt.plot(m.time,m.y.value,'r--',label='Output (y) estimated')\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 17: Model Predictive Control"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x15f69c21860>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\ns2dPDh8+TGxsLK+//jqnT59m5MiRl/VrkJ+fz5dffmnzIa5mzZoRFxfHnj17SEhIYPny5c78M4Sd\nJEHYoLXmhRde4IUXXuCee+7hs88+K12n36dPG62xfvEFjBwJpUksQriwTZs24enpycSJEwuntWvX\njptvvplRo0axbNmywulbt26lSZMmNGnSpNjtubu7ExUVVdhkeF5eHn/7298Km+Z+//33ATh58iTd\nu3cv7KiooJ0jf39/Hn/8ccLDw+nTp09h95pxcXF06dKFiIgIhg0bVtgOUs+ePXn66aeJioqiRYsW\nhdvZt28fUVFRREZGEhERUdh66meffVY4fcKECeTl5VXUoawUJEHY8Pzzz/PKK6/wwAMP8PHHH5eu\nhcTYWOjSBXbvhhUr4MknjSqtQjhCz55XDpZWUss0/yr27t1Lhw4dbM5r27Ytbm5u/PbbbwAsXbqU\nUaNGlbi9rKwstm3bxq233grARx99RGBgIDExMcTExPDBBx9w9OhRPv/8c/r3709cXBy//fZbYUuu\n6enpdOzYkX379tGjRw/+/ve/AzB27FhmzpzJ7t27adu2beF0MBrW3L59O//6178Kp8+fP58pU6YQ\nFxfHjh07CAkJ4cCBAyxbtoyff/6ZuLg43N3dHdIgniuT5yCK+Oc//8lrr73GQw89xLx58+zrN7pA\nXh6MHm10D7plC3Tq5LhAhXBBo0aNYunSpYSHh7Ny5crLTszWDh8+TGRkJEePHuW2224jIiICMJrm\n3r17N19++SVg9MVw6NAhOnXqxPjx48nJyeH2228vTBBubm6MGDECMDrsGT58OBcuXCA5OZkePXoA\nxlPO//d//1e47+HDhwOXmgkHo+OjV199lYSEBIYPH07z5s3ZsGEDsbGxdLL8H2dmZpap/abKTBKE\nlejoaJ5++mlGjhzJe++9Z39y2LYN2raFGjXgyy+NZjOkFzjhDJs3O3Z+EeHh4YUnb1tGjhxJv379\n6NGjBxEREdSrV8/mcgX3IM6dO8dNN93E6tWrGTJkCFprZs+eTf/+/a9YZ+vWraxdu5Z7772XJ554\ngrFjx16xjLKjtF7QVLi7uzu5ubkA3H333XTu3Jm1a9cycOBA3n//fbTWjBs3jtdff/2q26yq5BKT\nxdKlS5k4cSIDBw5k4cKF9l1WysiAJ54wnm94801jWps2khxEldW7d28uXrxIdHR04bTdu3cXXstv\n1qwZQUFBTJ8+/aqXlwCCgoJ44403Ck/C/fv3Z968eYW1mg4ePEh6ejrHjh2jXr16PPjggzzwwAPs\n3LkTuHQjHODzzz+nW7duBAYGUrt27cKYFi1aVFiaKM6RI0cICwvjscceY+jQoezevZs+ffrw5Zdf\nFjYNnpSUxLFjx0pzuCo/e1r0c9WholpzXbt2rfbw8NDdu3fX6enp9q20aZPWzZppDVo/8ojWJbSm\nKERFcYXWXE+cOKH/7//+T4eFhenWrVvrgQMH6oMHDxbOf/fdd7W3t7dOTk62uf7Ro0d1eHh44fv8\n/HwdERGht27dqvPy8vQzzzyj27Rpo8PDw3XPnj11cnKy/uSTT3R4eLiOjIzU3bp100eOHNFaa+3n\n56cff/xxHR4ernv16qXPnDmjtdZ6165dunPnzrpt27Z66NChOikpSWutdY8ePXRMTIzWWuuzZ8/q\nJk2aaK21fv3113Xr1q11u3btdP/+/XViYqLWWuulS5fqdu3a6bZt2+obbrhB//LLLxV7MJ2gPK25\nKm3ptKMy6tixo96xY0e5trF161b69+9P69at2bRpEzVr1rz6SnPnwuTJEBYGH31k1809ISrCgQMH\naNWqldlhuAx/f//CjoCEbba+M0qpWK31VZtzqNaXmHbu3MngwYMJDQ3lu+++Kzk5/PorFLScGBEB\nU6caNZUkOQghqqhqmyB+//13+vfvT+3atVm/fj3BwcFXLpSXB199BTfdZNxnePddY/rNNxvjVv3D\nCiGcT0oPjuVyCUIpdatS6g+l1J9KqemO2MexY8fo27cv7u7urF+/nhBbnfXMmwctW8Idd8DJk/Dv\nf8M//uGIcIQQwiW5VIJQSrkDc4EBQGtglFKqdUXv5+LFi9SpU4d169bR/Lrr4NAh+OQTeOqpSwtt\n2gTBwcbT0IcOwWOPQWlbcBXCASrzfUPhXOX9rrjacxBRwJ9a6yMASqmlwFBgf0XupEWLFux69VXc\nXnrJaEDPUo2NWrXgmWegdm0jYZSl1VYhHMjHx4fExETq1q1rV51/UX1prUlMTCxdA6NFuFqCaAQc\nt3qfAHS2XkAp9RDwEEDjxo3LvCO3Y8dg71649VbjHsNNN0GrVlDwcJwkB+GCQkJCSEhIKGxzSIiS\n+Pj42L6EbidXSxBXpbWOBqLBqOZa5g098ghMmlRRYQnhFJ6enjRt2tTsMEQ14VL3IIATwLVW70Ms\n0yqeFM+FEKJErpYgYoDmSqmmSikvYCSw2uSYhBCiWnKpS0xa61yl1GTge8AdWKC13mdyWEIIUS1V\n6qY2lFJngfK0nhUEnKugcCqSxFU6ElfpSFylUxXjaqK1tvF08OUqdYIoL6XUDnvaI3E2iat0JK7S\nkbhKpzrH5Wr3IIQQQrgISRBCCCFsqu4JIvrqi5hC4iodiat0JK7SqbZxVet7EEIIIYpX3UsQQggh\nilHlE8TVmg9XhlmW+buVUjc4IaZrlVKblFL7lVL7lFJTbCzTUyl1QSkVZxledHRclv3GK6X2WPZ5\nRXd9Jh2vllbHIU4plaKUmlpkGacdL6XUAqXUGaXUXqtpdZRS65VShyyvtYtZ12HN2RcT15tKqd8t\nn9XXSimbHaZf7XN3QFwzlFInrD6vgcWs6+zjtcwqpnilVFwx6zrkeBV3bjDt+2VPv6SVdcB42O4w\nEAZ4Ab8BrYssMxD4FlBAF2CbE+JqANxgGQ8ADtqIqyewxoRjFg8ElTDf6cfLxmd6CqMetynHC+gO\n3ADstZr2T2C6ZXw6MLMs30cHxNUP8LCMz7QVlz2fuwPimgFMs+OzdurxKjL/beBFZx6v4s4NZn2/\nqnoJorD5cK11NlDQfLi1ocBCbfgVqKWUauDIoLTWJ7XWOy3jqcABjJZsKwOnH68i+gCHtdbleUCy\nXLTWW4GkIpOHAp9axj8Fbrexqj3fxwqNS2u9Tmuda3n7K0b7Zk5VzPGyh9OPVwFltKV+F7CkovZn\nZ0zFnRtM+X5V9QRhq/nwoidie5ZxGKVUKNAe2GZj9o2WSwPfKqXCnRSSBn5QSsUqo2n1okw9Xhjt\ncxX3T2vG8SpQT2t90jJ+CqhnYxmzj914jNKfLVf73B3hUcvntaCYSyZmHq+bgdNa60PFzHf48Spy\nbjDl+1XVE4RLU0r5AyuAqVrrlCKzdwKNtdYRwGxgpZPC6qa1jsTo1W+SUqq7k/Z7VcpowHEI8IWN\n2WYdrytoo7zvUtUDlVLPAbnA4mIWcfbnPg/jUkgkcBLjco4rGUXJpQeHHq+Szg3O/H5V9QRhT/Ph\nzmti3IpSyhPjC7BYa/1V0fla6xStdZpl/BvAUykV5Oi4tNYnLK9ngK8xiq3WTDleFgOAnVrr00Vn\nmHW8rJwuuNRmeT1jYxmzvmv3AoOA0ZaTyxXs+NwrlNb6tNY6T2udD3xQzP7MOl4ewHBgWXHLOPJ4\nFXNuMOX7VdUThD3Nh68Gxlpq53QBLlgV5RzCcn3zI+CA1vqdYpapb1kOpVQUxmeV6OC4/JRSAQXj\nGIoX564AAAJASURBVDc49xZZzOnHy0qxv+rMOF5FrAbGWcbHAatsLOP05uyVUrcCTwFDtNYZxSxj\nz+de0XFZ37caVsz+zGr+/xbgd611gq2ZjjxeJZwbzPl+VfRdeFcbMGrdHMS4u/+cZdpEYKJlXAFz\nLfP3AB2dEFM3jCLibiDOMgwsEtdkYB9GTYRfgRudEFeYZX+/WfbtEsfLsl8/jBN+oNU0U44XRpI6\nCeRgXOe9H6gLbAAOAT8AdSzLNgS+Ken76OC4/sS4Ll3wPZtfNK7iPncHx7XI8v3ZjXESa+AKx8sy\n/ZOC75XVsk45XiWcG0z5fsmT1EIIIWyq6peYhBBClJEkCCGEEDZJghBCCGGTJAghhBA2SYIQQghh\nk4fZAQhRGSilCqoZAtQH8oCzlvcZWusbTQlMCAeSaq5ClJJSagaQprV+y+xYhHAkucQkRDkppdIs\nrz2VUluUUquUUkeUUm8opUYrpbZb+g5oZlkuWCm1QikVYxluMvcvEMI2SRBCVKx2GE94twLuAVpo\nraOAD4FHLcv8G3hXa90JuMMyTwiXI/cghKhYMdrSNpVS6jCwzjJ9D9DLMn4L0NrSdBRATaWUv7Y0\nNiiEq5AEIUTFumg1nm/1Pp9L/29uQBetdZYzAxOitOQSkxDOt45Ll5tQSkWaGIsQxZIEIYTzPQZ0\ntPSmth/jnoUQLkequQohhLBJShBCCCFskgQhhBDCJkkQQgghbJIEIYQQwiZJEEIIIWySBCGEEMIm\nSRBCCCFskgQhhBDCpv8H4C07n2GUhxgAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x15f688110f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from random import random\n",
    "from gekko import GEKKO\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "m = GEKKO()\n",
    "m.time = np.linspace(0,20,41)\n",
    "\n",
    "# Parameters\n",
    "mass = 500\n",
    "b = m.Param(value=50)\n",
    "K = m.Param(value=0.8)\n",
    "\n",
    "# Manipulated variable\n",
    "p = m.MV(value=0, lb=0, ub=100)\n",
    "p.STATUS = 1  # allow optimizer to change\n",
    "p.DCOST = 0.1 # smooth out gas pedal movement\n",
    "p.DMAX = 20   # slow down change of gas pedal\n",
    "\n",
    "# Controlled Variable\n",
    "v = m.CV(value=0)\n",
    "v.STATUS = 1  # add the SP to the objective\n",
    "m.options.CV_TYPE = 2 # squared error\n",
    "v.SP = 40     # set point\n",
    "v.TR_INIT = 1 # set point trajectory\n",
    "v.TAU = 5     # time constant of trajectory\n",
    "\n",
    "# Process model\n",
    "m.Equation(mass*v.dt() == -v*b + K*b*p)\n",
    "\n",
    "m.options.IMODE = 6 # control\n",
    "m.solve(disp=False)\n",
    "\n",
    "# get additional solution information\n",
    "import json\n",
    "with open(m.path+'//results.json') as f:\n",
    "    results = json.load(f)\n",
    "\n",
    "plt.figure()\n",
    "plt.subplot(2,1,1)\n",
    "plt.plot(m.time,p.value,'b-',label='MV Optimized')\n",
    "plt.legend()\n",
    "plt.ylabel('Input')\n",
    "plt.subplot(2,1,2)\n",
    "plt.plot(m.time,results['v1.tr'],'k-',label='Reference Trajectory')\n",
    "plt.plot(m.time,v.value,'r--',label='CV Response')\n",
    "plt.ylabel('Output')\n",
    "plt.xlabel('Time')\n",
    "plt.legend(loc='best')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 18: Debugging Resources\n",
    "\n",
    "Applications may need a more detailed inspection to find errors in programming syntax, errors in modeling assumptions, or to generate good initial guess values. The GEKKO or the solver solution reports syntax errors. Setting m.solve(disp=True) displays the solver output with a message on the line of code that is unsuccessful. Naming the variables such as name='state' is helpful to display the equations in a readable form.\n",
    "\n",
    "Other strategies for obtaining a successful solution include:\n",
    "\n",
    "* Increase the number of iterations with MAX_ITER (0-1000+)\n",
    "* Increase the diagnostic level with DIAGLEVEL (0-10)\n",
    "* Change the solver with SOLVER (1-5)\n",
    "* Calculate model SENSITIVITY (1)\n",
    "* Solve a square problem with # Variables = # Equations\n",
    "* Set COLDSTART to initialize problem (0-2)\n",
    "\n",
    "Additional [modeling](http://apmonitor.com/do/index.php/Main/ModelFormulation), [initialization](http://apmonitor.com/do/index.php/Main/ModelInitialization), and [decomposition](https://www.sciencedirect.com/science/article/pii/S0098135415001179) tips may be helpful. There is also an online [discussion group](http://apmonitor.com/wiki/index.php/Main/UsersGroup), [video playlist](https://www.youtube.com/playlist?list=PLLBUgWXdTBDjcqDl2e5F_hcBjEc6vjr1X), [GEKKO documentation](http://gekko.readthedocs.io/en/latest/), and [APMonitor documentation](http://apmonitor.com/wiki/index.php/Main/HomePage) as additional resources."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------- Follow local path to view files --------------\n",
      "C:\\Users\\johnh\\AppData\\Local\\Temp\\tmp7c4y0_fmgk_model18\n",
      "--------------------------------------------------------\n",
      "apm 10.5.113.123_gk_model18 <br><pre> ----------------------------------------------------------------\n",
      " APMonitor, Version 0.8.1\n",
      " APMonitor Optimization Suite\n",
      " ----------------------------------------------------------------\n",
      " \n",
      " \n",
      " --------- APM Model Size ------------\n",
      " Each time step contains\n",
      "   Objects      :            0\n",
      "   Constants    :            0\n",
      "   Variables    :            2\n",
      "   Intermediates:            0\n",
      "   Connections  :            0\n",
      "   Equations    :            1\n",
      "   Residuals    :            1\n",
      " \n",
      " Number of state variables:              1\n",
      " Number of total equations: -            1\n",
      " Number of slack variables: -            0\n",
      " ---------------------------------------\n",
      " Degrees of freedom       :              0\n",
      " \n",
      " ----------------------------------------------\n",
      " Steady State Optimization with APOPT Solver\n",
      " ----------------------------------------------\n",
      " \n",
      " Iter    Objective  Convergence\n",
      "    0  0.00000E+00  5.00000E+00\n",
      "    1  0.00000E+00  5.00000E+00\n",
      " Successful solution\n",
      " \n",
      " ---------------------------------------------------\n",
      " Solver         :  APOPT (v1.0)\n",
      " Solution time  :   1.300000000628643E-002 sec\n",
      " Objective      :   0.000000000000000E+000\n",
      " Successful solution\n",
      " ---------------------------------------------------\n",
      " \n",
      " \n",
      " Generating Sensitivity Analysis\n",
      " Writing apm_sens_A_matrix.txt\n",
      " Writing sensitivity.txt\n",
      " Writing sensitivity.htm\n",
      "x: [5.0]\n"
     ]
    }
   ],
   "source": [
    "from gekko import GEKKO\n",
    "\n",
    "m = GEKKO()                 # create GEKKO model\n",
    "\n",
    "print('--------- Follow local path to view files --------------')\n",
    "print(m.path)               # show source file path\n",
    "print('--------------------------------------------------------')\n",
    "\n",
    "# test application\n",
    "u = m.FV(value=5,name='u')  # define fixed value\n",
    "x = m.SV(name='state')      # define state variable\n",
    "m.Equation(x==u)            # define equation\n",
    "m.options.COLDSTART = 1     # coldstart option\n",
    "m.options.DIAGLEVEL = 0     # diagnostic level (0-10)\n",
    "m.options.MAX_ITER = 500    # adjust maximum iterations\n",
    "m.options.SENSITIVITY = 1   # sensitivity analysis\n",
    "m.options.SOLVER = 1        # change solver (1=APOPT,3=IPOPT)\n",
    "m.solve(disp=True)          # solve locally (remote=False)\n",
    "print('x: ' + str(x.value)) # print variable value"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
